Download presentation
Presentation is loading. Please wait.
Published byZoe Chandler Modified over 9 years ago
1
Type Inference with Run-time Logs Ravi Chugh, Ranjit Jhala, Sorin Lerner University of California, San Diego
2
Motivation: Dynamic Languages Dynamically-typed languages – Enable rapid prototyping – Facilitate inter-language development Statically-typed languages – Prevent certain run-time errors – Enable optimized execution – Provide checked documentation Many research efforts to combine both – Recent popularity of Python, Ruby, and JavaScript has stoked the fire 2
3
Gradual Type Systems Many attempts at fully static type systems – Often require refactoring and annotation – Some features just cannot be statically typed Gradual type systems provide a spectrum – Some expressions have types, statically-checked – Others are dynamic, fall back on run-time checks Challenges – Granularity, guarantees, blame tracking, and... 3
4
... Inference! Goal: migrate programs from dynamic langs Programmer annotation burden is currently 0 A migration strategy must require ~0 work – Even modifying 1-10% LOC in a large codebase can be prohibitive 4
5
The Challenge: Inference 5 Goal: practical type system polymorphism def id(x) { return x }; 1 + id(2); “hello” ^ id(“world”); polymorphism id : ∀ X. X → X
6
The Challenge: Inference 6 Goal: practical type system subtypingpolymorphism def succA(x) { return (1 + x.a) }; succA({a=1}); succA({a=1;b=“hi”}); subtyping {a:Int;b:Str} <: {a:Int}
7
The Challenge: Inference bounded quantification 7 Goal: practical type system subtypingpolymorphism 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
8
The Challenge: Inference bounded quantification 8 Goal: practical type system subtypingpolymorphism dynamic n := if b then 0 else “bad”; m := if b then n + 1 else 0; dynamic n : dynamic
9
The Challenge: Inference bounded quantification 9 Goal: practical type system subtypingpolymorphism dynamic other features...
10
The Challenge: Inference bounded quantification 10 Goal: practical type system subtypingpolymorphism dynamic other features... System ML ✓
11
The Challenge: Inference bounded quantification 11 Goal: practical type system subtypingpolymorphism dynamic other features... System F ✗
12
The Idea Use run-time executions to help inference Program may have many valid types – But particular execution might rule out some Dynamic language programmers test a lot – Use existing test suites to help migration 12
13
Route: Inference w/ Run-time Logs bounded quantification 13 subtyping + polymorphism omit higher-order functions System E System E ≤
14
First Stop bounded quantification 14 subtyping + polymorphism omit higher-order functions System E System E ≤ System E −
15
E − Type System Expression and function types τ ::= | Int | Bool |... | {f i :τ i } | X σ ::= ∀ X i. τ 1 → τ 2 Typing rules prevent field-not-found and primitive operation errors 15
16
def id (a) { a } def id[A] (a:A) { a } : ∀ A. A → A def id[] (a:Int) { a } : Int → Int def id[B,C] (x:B*C) { a } : ∀ B,C. B*C → B*C Infinitely many valid types for id... 16
17
... but ∀ A. A → A is the principal type 17 ∀ A. A → A ∀ B,C. B*C → B*C Int → Int
18
... but ∀ A. A → A is the principal type More general than every other type Allows id to be used in most different ways 18 ∀ B,C. B*C → B*C ∀ B. B*B → B*B Int*Int → Int*IntInt*Bool → Int*Bool ∀ A. A → A Int → Int
19
def readF (o) { o.f } def readF[F] (o:{f:F}) { o.f } : ∀ F. {f:F} → F This 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
20
def hasF (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} allows hasF({f=1;g=2}).g allows hasF({f=1})
21
E − Static Type Inference E − lacks principal types – Cannot assign type just from definition – Need to consider calling contexts Our approach is iterative – Impose minimal constraints on argument – If a calling context requires an additional field to be tracked, backtrack and redo the function 21
22
22 def hasF(x) { let _ = x.f in x } def main1() { hasF({f=1}) } Iterative Inference – Example 1 X <: {f:F} hasF : ∀ F. {f:F} → {f:F} x Constraints on xS olution X = {f:F} x ✓ “this record type came from the program variable x ”
23
23 def hasF(x) { let _ = x.f in x } def main2() { let z = {f=1;g=2} in hasF(z).g } Iterative Inference – Example 2 X <: {f:F} hasF : ∀ F. {f:F} → {f:F} x Constraints on xS olution X = {f:F} x ✗*✗* hasF(z) : {f:Int} x so can’t project on g, unless... X <: {g:G}
24
24 def hasF(x) { let _ = x.f in x } def main2() { let z = {f=1;g=2} in hasF(z).g } Iterative Inference – Example 2 X <: {f:F} hasF : ∀ F,G. {f:F;g:G} → {f:F;g:G} x Constraints on xS olution X <: {g:G} X = {f:F;g:G} x ✓
25
25 def hasF(x) { let _ = x.f in x } def main3() { let z = {f=1;g=2} in hasF(z).g; hasF({f=1}) } Iterative Inference – Example 3 X <: {f:F} Constraints on x X <: {g:G} hasF : ∀ F,G. {f:F;g:G} → {f:F;g:G} x S olution X = {f:F;g:G} x
26
26 def hasF(x) { let _ = x.f in x } def main3() { let z = {f=1;g=2} in hasF(z).g; hasF({f=1}) } Iterative Inference – Example 3 X <: {f:F} Constraints on x X <: {g:G} hasF : ∀ F,G. {f:F;g:G} → {f:F;g:G} x S olution X = {f:F;g:G} x ✓ ✗
27
E − Type Inference with Run-time Logs Evaluation can log caller-induced constraints 1.Wrap all values with sets of type variables 2.When a value passed to arg x, add X x tag 3.When a value with tag X x.l projected on field f, record X x.l <: {f : X x.l.f } Iteration 0 of modified inference looks in log for caller-induced constraints 27
28
28 def hasF(x) { let _ = x.f in x } def main2() { let z = {f=1;g=2} in hasF(z).g } main2() ⇒ let z = {f=1;g=2} in hasF(z).g ⇒ let z = [{f=1;g=2},{}] in hasF(z).g ⇒ hasF([{f=1;g=2},{X x }]).g ⇒ (let _ = [{f=1;g=2},{X x }].f in [{f=1;g=2},{X x }]).g ⇒ (let _ = [1,{X x.f }] in [{f=1;g=2},{X x }]).g ⇒ [{f=1;g=2},{X x }].g ⇒ [2,{X x.g }] Evaluation Run-time log X x <: {g : X x.g } X x <: {f : X x.f } Caller-induced constraint
29
System E − Summary 29 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
30
Next Stop bounded quantification 30 subtyping + polymorphism System E System E ≤ System E −
31
If-expressions Type is a supertype of branch types 31 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} : {f:Top} : Top
32
def choose (y,z) { if 1 y.n > 0 then y else z } Four valid incomparable types: 32 ∀ A. {n:Int}*{} → {} ∀ A. {n:Int}*{n:Top} → {n:Top} {n:Int}*{n:Int} → {n:Int} ∀ B. {n:Int;b:B}*{n:Int;b:B} → {n:Int;b:B}
33
33 def choose(y,z) { if 1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } Iterative Inference – Example Constraints “this record type came from the if-expression 1” N = IntY <: {n:N} choose : {n:Int}*{} → {} 1 Iteration 0
34
34 def choose(y,z) { if 1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } Iterative Inference – Example Y <: {n:N} choose : {n:Int}*{} → {} 1 Constraints Iteration 0 choose : {n:Int}*{n:Top 1.n } → {n:Top 1.n } 1 Iteration 1 N = IntZ <: {n:M} ✗*✗* t : {} 1 so can’t project on n
35
35 def choose(y,z) { if 1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } Iterative Inference – Example Y <: {n:N} choose : {n:Int}*{} → {} 1 Constraints Iteration 0 choose : {n:Int}*{n:Top 1.n } → {n:Top 1.n } 1 Iteration 1 choose : {n:Int}*{n:Int} → {n:Int} 1 Iteration 2 N = IntZ <: {n:M}N = M ✗*✗* t.n : Top 1.n so can’t add
36
36 def choose(y,z) { if 1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } Iterative Inference – Example Y <: {n:N} choose : {n:Int}*{} → {} 1 Constraints Iteration 0 choose : {n:Int}*{n:Top 1.n } → {n:Top 1.n } 1 Iteration 1 choose : {n:Int}*{n:Int} → {n:Int} 1 Iteration 2 N = IntZ <: {n:M}N = M ✓
37
System E Summary Lacks principal types Has iterative inference – Use subscripts for record types from if-exps Run-time info removes iteration, as before 37
38
Last Stop bounded quantification 38 subtyping + polymorphism System E ≤ System E System E −
39
39 def hasF (x) { let _ = x.f in x } Now there is a best type for hasF Each call site can instantiate X differently 39 ∀ F. {f:F} → {f:F} ∀ F,G. {f:F;g:G} → {f:F;g:G} ∀ F, X<:{f:F}. X → X
40
def choose (y,z) { if 1 y.n > 0 then y else z } 40 ∀ 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}*{} → {}
41
def choose (y,z) { if 1 y.n > 0 then y else z } 41 ∀ Y<:{n:Int}. Y * Y → Y allows choose({n=1},{n=2}).n allows choose({n=1},{}) and choose({n=1,b=true}, {n=2,b=false}).b Neither type is better {n:Int}*{} → {}
42
Sharing Bounded Type Variables E ≤ lacks principal types Can type variables for y and z be shared? If their separate bounds are compatible Y<:{n:Int} and Z<:{} can be combined to {n:Int} Y<:{n:Int} and Z<:{n:Bool} cannot be combined 42
43
E ≤ Inference For all program variables returned by an if: 1.If bounds not compatible, use separate variables 2.Otherwise, use same type variable A.All call sites well-typed B.Otherwise, restart and keep vars separate Using separate variables is just like System E Now there is a second cause for restarting 43
44
E ≤ Inference with Run-time Logs Know when to share from run-time info? Can’t determine if all call sites well-typed – even if actual has a field, its static type might not Can determine if some call site is not – if an actual doesn’t have field, static type will not So can eliminate some iteration but not all 44
45
System E ≤ Summary Lacks principal types Primary new challenge: determining when to use same type variable for y and z Static inference has new source of iteration – Cannot be eliminated with run-time info 45
46
Summary bounded quantification 46 subtyping + polymorphism System E ≤ System E System E −
47
Summary Iterative static inference for E ≤ – first-order functions, records – polymorphism, subtyping – bounded quantification Run-time information improves algorithms – reduces worst-case complexity – (not counting overhead for instrumented eval) 47
48
Future 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 F – does inference become easier with run-time info? – if so, extend with more features – if not, heuristic-based approaches for migration 48
49
Goseichou arigatou gozaimashita! Released under Creative Commons Attribution 2.0 Generic LicenseCreative Commons Attribution 2.0 Generic License 49 Original photoOriginal photo by Alaskan Dude
50
Extra Slides 50
51
Function definitions Function calls Program is sequence of function definitions Typed vs. Untyped Syntax 51 def y[A 1,...,A n ](x:τ){ e }def y(x){ e’ } y[τ 1,...,τ n ](e)y(e’)
52
Bounded Quantification 52 def y[ A 1 <:τ 1,..., A n <:τ n ] (x:τ) { e } Type parameters now have bounds
53
Bounded Quantification With arbitrary subtyping constraints, choose has a principal type 53 ∀ Y,Z. (Y Y*Z → Z
54
Related Work Complete inference for ML + records [Remy 89] – limited by ML polymorphism – and fields cannot be forgotten Type 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 rest – even partial inference for F undecidable [Pfenning 88] Type checking for F ≤ is undecidable [Pierce 91] 54
55
Related Work Static type systems for dynamic languages – type systems for JavaScript [Thiemann 05, et al] – Typed Scheme [Tobin-Hochstadt and Felleisen 08] – Diamondback Ruby [Furr et al 09 11] Gradual type systems – functions [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 55
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.