COMPLETE MONITORS FOR GRADUAL TYPES Ben Greenman Matthias - - PowerPoint PPT Presentation
COMPLETE MONITORS FOR GRADUAL TYPES Ben Greenman Matthias - - PowerPoint PPT Presentation
Ben Greenman Matthias Felleisen Christos Dimoulas at at at COMPLETE MONITORS FOR GRADUAL TYPES Ben Greenman Matthias Felleisen Christos Dimoulas at at at COMPLETE MONITORS FOR GRADUAL TYPES a careful analysis of the mixed-typed
COMPLETE MONITORS FOR GRADUAL TYPES
Ben Greenman Matthias Felleisen Christos Dimoulas
at at at
a careful analysis
- f the mixed-typed
design space
Type soundness is not enough Complete monitoring is crucial for meaningful gradual types "Incomplete" monitoring provides a way to measure the quality of blame errors *from ESOP 2012 *
Mixed-Typed Language
Mixed-Typed Language
U T U U T
Untyped/Typed mix
U
= untyped code
T
= simply-typed (no 'Dynamic' type) code
A Few Motivations
U T U U T
A Few Motivations
U T U U T
Prototyping
A Few Motivations
U T U U T
Prototyping write untyped code, rely on types
A Few Motivations
U T U U T
Prototyping write untyped code, rely on types Re-Use
A Few Motivations
U T U U T
Prototyping write untyped code, rely on types Re-Use write typed code, use old libraries
Many Implementations ...
JavaScript Flow + Racket Typed Racket + Python Reticulated + Python Mypy + PHP Hack + JavaScript TypeScript +
Many Implementations ...
JavaScript Flow + Racket Typed Racket + Python Reticulated + Python Mypy + PHP Hack + JavaScript TypeScript +
... diffcult to compare
UTU U T
Many Models, too
GTLC AGT λH λ*
→
UTU U T
Goal: Characterize the Landscape
Non-Goal: Restrict Landscape
Warmup: Optional Typing / Erasure
Example: Optional Typing
function f (x : [N,N]) { ... fst x ... }
T
Example: Optional Typing
function f (x : [N,N]) { ... fst x ... }
T
f(9)
U
Example: Optional Typing
function f (x : [N,N]) { ... fst x ... }
T
f(9)
U
Error: 9 is not a pair
Example: Optional Typing
function f (x : [N,N]) { ... fst x ... }
T
f(9)
U
Error: 9 is not a pair types are meaningless at run-time cannot help debug a faulty program
= Does Not Preserve Types
Uni sound
= Does Not Preserve Types
Uni sound
"type" sound
ICFP '18
ICFP '18 : Three Semantics, Soundnesses
ICFP '18 : Three Semantics, Soundnesses
Erasure semantics
- types predict nothing
ICFP '18 : Three Semantics, Soundnesses
Erasure semantics
- types predict nothing
Transient semantics
- types predict the top-level shape of values
- enforced by tag checks
ICFP '18 : Three Semantics, Soundnesses
Erasure semantics
- types predict nothing
Transient semantics
- types predict the top-level shape of values
- enforced by tag checks
Natural semantics
- types predict the full behavior of values
- enforced by higher-order wrappers
ICFP '18 : Three Semantics, Soundnesses
Erasure semantics
- types predict nothing
Transient semantics
- types predict the top-level shape of values
- enforced by tag checks
Natural semantics
- types predict the full behavior of values
- enforced by higher-order wrappers
Uni sound ⌊T⌋ sound T sound
Erasure semantics
- types predict nothing
Transient semantics
- types predict the top-level shape of values
- enforced by tag checks
Natural semantics
- types predict the full behavior of values
- enforced by higher-order wrappers
ICFP '18: A Spectrum of Type Soundness
Uni sound
ICFP '18: A Spectrum of Type Soundness
Uni sound ⌊T⌋ sound Uni sound T sound Erasure Natural Transient
⌊T⌋ sound T sound Natural Transient
⌊T⌋ sound T sound Natural Transient
Transient semantics
- types predict the top-level shape of values
- enforced by tag checks
Natural semantics
- types predict the full behavior of values
- enforced by higher-order wrappers
⌊T⌋ sound T sound
Transient semantics
- types predict the top-level shape of values
- enforced by tag checks
Natural semantics
- types predict the full behavior of values
- enforced by higher-order wrappers
⌊T⌋ sound T sound Natural Transient
⌊T⌋ sound T sound Natural Transient Amnesic
Amnesic semantics
- enforce tag checks ⌊T⌋
with higher-order wrappers
- same behavior as Transient
- same type soundness as Natural
OOPSLA '19
Greenberg POPL '15 Castagna, Lanvin ICFP '17
Type Soundness is NOT ENOUGH
⌊T⌋ sound Uni sound T sound ??? Erasure Natural Transient Amnesic
Example: Transient/Amnesic vs. Natural
Example: Transient/Amnesic vs. Natural
Prototyping
Example: Transient/Amnesic vs. Natural
Prototyping Library Re-Use
Example: Transient/Amnesic vs. Natural
Prototyping Library Re-Use Combine: untyped script + typed API + untyped library via a higher-order value
Example: Transient/Amnesic vs. Natural
- 1. plot data
- 2. listen for a click
- 3. draw an image
Clickable Plot
1
Example: Transient/Amnesic vs. Natural
- 1. plot data
- 2. listen for a click
- 3. draw an image
Clickable Plot
2
Example: Transient/Amnesic vs. Natural
- 1. plot data
- 2. listen for a click
- 3. draw an image
Clickable Plot
3
Example: interactive plot
Client
U
Library
U
API
T
Example: interactive plot
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Library
U
API
T
Example: interactive plot
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
API
T
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Promises a pair of numbers
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Promises a pair of numbers
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Promises a pair of numbers Expects a pair of numbers
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Sends MouseEvt value
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Sends MouseEvt value
[N,N] != MouseEvt
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Sends MouseEvt value
[N,N] != MouseEvt
- Q. Does h receive
bad input?
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
- Q. Does h receive
bad input?
Example: interactive plot
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
- Q. Does h receive
bad input?
- A. Yes, Trans/Amns
- A. No, Natural
U T U
U T U
h
U T U
h
U T U
h(evt)
- Q. Do types guard the callback channel?
U T U
h(evt)
- Q. Do types guard the callback channel?
Transient/Amnesic: no, because the channel is between two untyped components Natural: yes, because the channel was created via typed code
U T U
h(evt)
- Q. Do types guard the callback channel?
Type Soundness ⇒ yes Complete Monitoring ⇒ yes
⌊T⌋ sound Uni sound T sound Complete monitoring Erasure Natural Transient Amnesic
Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring
Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring BLAME
Natural, Blame
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Natural, Blame
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Error: MouseEvt is not a pair
Natural, Blame
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Error: expected [N,N] got MouseEvt blaming Library assuming the API types are correct
Transient/Amnesic, Blame
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Transient/Amnesic, Blame
class ClickPlot { constructor(
- nClick){...}
mouseHandler(evt){ i = onClick(evt) // draw i } show(){...} } Library
U
type ClickPlot { constructor( ([N,N]) => Image) mouseHandler : (MouseEvt) => Void show : () => Void } API
T
function h(x) { if (0 < fst x): pumpkin else: fish } p = ClickPlot(h) p.show() // click Client
U
Error: <obj> is not a pair blaming: Client / API API / Library
U T U U T
v
Blame Properties
- 1. blame only
responsible edges
- 2. blame all
responsible edges
- 3. blame exactly the responsible edges
U T U U T
v
Blame Properties
- 1. blame only
responsible edges
- 2. blame all
responsible edges
- 3. blame exactly the responsible edges
Blame Soundness Blame Completeness
- B. Soundness + B. Completeness
Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring blame soundness blame completeness Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring blame soundness blame completeness
Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring blame soundness blame completeness Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring blame soundness blame completeness
Every Typed Language is Mixed-Typed
Many typed languages trust untyped code
Every Typed Language is Mixed-Typed
Many typed languages trust untyped code Gradual typing makes these boundaries visible ...
U T
Every Typed Language is Mixed-Typed
Many typed languages trust untyped code Gradual typing makes these boundaries visible ...
U T
... and challenges our notions of types and what types mean
Complete monitoring strengthens type soundness for programs that compose typed and untyped and enables precise statements about the quality of blame
github.com/nuprl/gfd-oopsla-2019
Code + Proofs:
Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring* blame soundness* blame completeness* Natural Transient Amnesic type soundness
T ⌊T⌋ T
complete monitoring* blame soundness* blame completeness*
⌊T⌋ sound Uni sound T sound Complete monitoring Erasure Natural Transient Amnesic