Ravi Chugh Motivation Dynamic Languages Dynamicallytyped languages Enable rapid prototyping Facilitate interlanguage development Staticallytyped languages Prevent certain runtime errors Enable optimized execution ID: 760321
Download Presentation The PPT/PDF document "Type Inference with Run-time Logs" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Type Inferencewith Run-time Logs
Ravi Chugh
Slide2Motivation: Dynamic Languages
Dynamically-typed languagesEnable rapid prototypingFacilitate inter-language developmentStatically-typed languagesPrevent certain run-time errorsEnable optimized executionProvide checked documentationMany research efforts to combine bothRecent popularity of Python, Ruby, and JavaScript has stoked the fire
2
Slide3Gradual Type Systems
Many attempts at fully static type systemsOften require refactoring and annotationSome features just cannot be statically typedGradual type systems provide a spectrumSome expressions have types, statically-checkedOthers are dynamic, fall back on run-time checksChallengesGranularity, guarantees, blame tracking, and ...
3
Slide4... Inference!
Goal: migrate programs from dynamic langsProgrammer annotation burden is currently 0A migration strategy must require ~0 workEven modifying 1-10% LOC in a large codebasecan be prohibitive
4
Slide5The Challenge: Inference
5
Goal: practical type system
polymorphism
def id(x) { return x };
1 + id(2);
“hello” ^ id(“world”);
polymorphism
id : ∀X. X → X
Slide6The Challenge: Inference
6
Goal: practical type system
subtyping
polymorphism
def succA(x) {
return (1 + x.a)
};
succA({a=1});
succA({a=1;b=“hi”});
subtyping
{a:Int;b:Str} <: {a:Int}
Slide7The Challenge: Inference
bounded quantification
7
Goal: practical type system
subtyping
polymorphism
def incA(x) {
x.a := 1 + x.a;
return x
};
incA({a=1}).a;
incA({a=1;b=“hi”}).b;
bounded quantification
incA
:
∀X<:{a:Int}.
X
→
X
Slide8The Challenge: Inference
bounded quantification
8
Goal: practical type system
subtyping
polymorphism
dynamic
n := if b then 0
else “bad”;
m := if b then n + 1
else 0;
dynamic
n : dynamic
Slide9The Challenge: Inference
bounded quantification
9
Goal: practical type system
subtyping
polymorphism
dynamic
other features...
Slide10The Challenge: Inference
bounded quantification
10
Goal: practical type system
subtyping
polymorphism
dynamic
other features...
System ML
✓
Slide11The Challenge: Inference
bounded quantification
11
Goal: practical type system
subtyping
polymorphism
dynamic
other features...
System F
✗
Slide12The Idea
Use run-time executions to help inferenceProgram may have many valid typesBut particular execution might rule out someDynamic language programmers test a lotUse existing test suites to help migration
12
Slide13Route: Inference w/ Run-time Logs
bounded quantification
13
subtyping
+
polymorphism
omit higher-order functions
System E
System E
≤
Slide14First Stop
bounded quantification
14
subtyping
+
polymorphism
omit higher-order functions
System E
System E
≤
System E
−
Slide15E− Type System
Expression and function types τ ::= | Int | Bool | ... | {fi:τi} | X σ ::= ∀Xi. τ1 → τ2Typing rules prevent field-not-found and primitive operation errors
15
Slide16def id (a) { a }def id[A] (a:A) { a } : ∀A. A → Adef id[] (a:Int) { a } : Int → Intdef id[B,C] (x:B*C) { a } : ∀B,C. B*C → B*CInfinitely many valid types for id...
16
Slide17... but ∀A. A → A is the principal type
17
∀A. A → A
∀B,C. B*C → B*C
Int → Int
Slide18... but ∀A. A → A is the principal typeMore general than every other typeAllows id to be used in most different ways
18
∀B,C. B*C → B*C
∀B. B*B → B*B
Int*Int
→ Int*Int
Int*Bool → Int*Bool
∀A. A →
A
Int
→ Int
Slide19def readF (o) { o.f }def readF[F] (o:{f:F}) { o.f } : ∀F. {f:F} → FThis is the best type
19
∀F. {f:F} → F
∀F,G. {f:F;g:G} → F
{f:Int} → Int
∀G. {f:Int;g:G} → Int
Slide20def foo (x) { let _ = x.f in x }Two valid types:Neither is better than the other
20
∀F. {f:F} → {f:F}
∀F,G. {f:F;g:G} → {f:F;g:G}
allowsfoo({f=1;g=2}).g
allows
foo({f=1})
Slide21E− Static Type Inference
E− lacks principal typesCannot assign type just from definitionNeed to consider calling contextsOur approach is iterativeImpose minimal constraints on argumentIf a calling context requires an additional field to be tracked, backtrack and redo the function
21
Slide2222
22
def foo (x) { let _ = x.f in o }
def main () { foo({f=1}) }
Iterative Inference – Example 1
X <: {f:F}
foo
: ∀F. {f:F} → {f:F}x
Constraints on arg of foo
Solution
X = {f:F}
x
✓
“this record type came from the program variable
x”
Slide2323
23
def foo (x) { let _ = x.f in o }
def main () { let z = {f=1;g=2} in foo(z).g }
Iterative Inference – Example 2
X <: {f:F}
foo : ∀F. {f:F} → {f:F}x
Constraints on arg of foo
Solution
X = {f:F}
x
✗
*
foo(z) : {f:Int}x so can’t project on g, unless...
X <: {g:G}
Slide2424
24
def foo (x) { let _ = x.f in o }
def main () { let z = {f=1;g=2} in foo(z).g }
Iterative Inference – Example 2
X <: {f:F}
foo
: ∀F,G. {f:F;g:G} → {f:F;g:G}x
Constraints on arg of foo
Solution
X <: {g:G}
X = {f:F;g:G}x
✓
Slide2525
25
def foo (x) { let _ = x.f in o }
def main () { let z = {f=1;g=2} in foo(z).g; foo({f=1}) }
Iterative Inference – Example 3
X <: {f:F}
Constraints on arg of foo
X <: {g:G}
foo
: ∀F,G. {f:F;g:G} → {f:F;g:G}x
Solution
X
=
{f:F;g:G}
x
Slide2626
26
def foo (x) { let _ = x.f in o }
def main () { let z = {f=1;g=2} in foo(z).g; foo({f=1}) }
Iterative Inference – Example 3
X <: {f:F}
Constraints on arg of foo
X <: {g:G}
foo
: ∀F,G. {f:F;g:G} → {f:F;g:G}x
Solution
X = {f:F;g:G}x
✓
✗
Slide27System E− Summary
27
Fully static inference needs to iterate, but can optimize with run-time information
Can wrap run-time values with sets of type variables and record field read constraints
If all expressions executed, then
log contains all caller-induced constraints
no need for iteration
Slide28Next Stop
bounded quantification
28
subtyping
+
polymorphism
System E
System E
System E
≤
System E
−
Slide29If-expressions
Type is a supertype of branch types
29
if b then 1 else 2
if b then 1 else true
if b then {f=1; g=“”} else {f=2; h=true}
if b then {f=“”} else {f=true}
: Int
: {f:Int}
✗
: {}
Slide30def bar (y,z) { if1 y.n > 0 then y else z }Three valid incomparable types:
30
∀A. {n:Int}*{} → {}
∀A. {n:Int}*{n:Int} → {n:Int}
∀B.
{n:Int;b:B}*{n:Int;b:B}
→
{n:Int;b:B}
Slide31System E Summary
Lacks principal typesHas iterative inferenceUse subscripts for record types from if-expressionsRun-time info removes iteration, as before
31
Slide32Last Stop
bounded quantification
32
subtyping
+
polymorphism
System E
≤
System E
≤
System E
System E
−
Slide3333
def foo (x) { let _ = x.f in x }Now there is a best type for fooEach call site can instantiate X differently
33
∀F. {f:F} → {f:F}
∀F,G. {f:F;g:G} → {f:F;g:G}
∀F, X<:{f:F}. X → X
Slide34def bar (y,z) { if1 y.n > 0 then y else z }
34
∀Y<:{n:Int}. Y
*
Y
→ Y
{n:Int}*{n:Int}
→ {n:Int}
∀B. {n:Int;b:B}*{n:Int;b:B} → {n:Int;b:B}
{n:Int}*{}
→
{}
Slide35def bar (y,z) { if1 y.n > 0 then y else z }
35
∀Y<:{n:Int}. Y * Y → Y
allowsbar({n=1},{n=2}).n
allowsbar({n=1},{})
andbar({n=1,b=true}, {n=2,b=false}).b
Neither type is better
{n:Int}*{}
→
{}
Slide36System E≤ Summary
Lacks principal typesPrimary new challenge: determining when to use same type variable for y and zStatic inference has new source of iterationCannot be eliminated with run-time info
36
Slide37Summary
bounded quantification
37
subtyping
+
polymorphism
System E
≤
System E
System E
−
Slide38Summary
Iterative static inference for E≤ first-order functions, recordspolymorphism, subtypingbounded quantificationRun-time information improves algorithmsreduces worst-case complexity(not counting overhead for instrumented eval)
38
Slide39Future Work
Direction #0: Prove formal properties for E≤Direction #1: Extend E≤recursion, recursive types, dynamic, classes, ...is there still static inference?how can run-time info help?can existing programs be encoded in E?Direction #2: Inference for Fdoes inference become easier with run-time info?if so, extend with more featuresif not, heuristic-based approaches for migration
39
Slide40Thanks!
Released under Creative Commons Attribution 2.0 Generic License
40
Original photo
by Alaskan
Dude
Slide41Extra Slides
41
Slide42Function definitions Function callsProgram is sequence of function definitions
Typed vs. Untyped Syntax
42
def y[A1,...,An](x:τ){ e }
def y(x){ e’ }
y[τ1,...,τn](e)
y(e’)
Slide43Bounded Quantification
43
def y[ A1<:τ1 , ... , An<:τn ] (x:τ) { e }
Type parameters now have bounds
Slide44Related Work
Complete inference for ML + records [Remy 89]limited by ML polymorphismand fields cannot be forgottenType inference for F is undecidable [Wells 94]Local type inference for F [Pierce et al, Odersky et al, et al]require top-level annotations, try to fill in resteven partial inference for F undecidable [Pfenning 88]Type checking for F≤ is undecidable [Pierce 91]
44
Slide45Related Work
Static type systems for dynamic languagestype systems for JavaScript [Thiemann 05, et al]Typed Scheme [Tobin-Hochstadt and Felleisen 08]Diamondback Ruby [Furr et al 09 11]Gradual type systemsfunctions [Thatte 90, Cartwright and Fagan 91, Siek and Taha 06]objects [Siek and Taha 07, Wrigstad et al 10, Bierman et al 10]Coercion insertion [Henglein/Rehof 95, Siek/Vachharajani 08] do not deal with records
45