Type Inference with Run-time Logs
-
Upload
emily-jenkins -
Category
Documents
-
view
29 -
download
1
description
Transcript of Type Inference with Run-time Logs
![Page 1: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/1.jpg)
Type Inferencewith Run-time Logs
Ravi Chugh
![Page 2: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/2.jpg)
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
![Page 3: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/3.jpg)
3
Static Type Systems
• Many attempts at fully static type systems– Flow sensitive types, occurrence types, ...– Often require refactoring and annotation– Some features just cannot be statically typed
• Retrofitting existing language unlikely– Could work for a new language– But we want to migrate existing programs
![Page 4: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/4.jpg)
4
Gradual Type Systems• Typing is not all-or-nothing– Some expressions have types, others are dynamic
• Typed portions checked in standard ways• Untyped portions fall back on run-time checks• Challenges– Granularity– Guarantees– Blame tracking– and ...
![Page 5: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/5.jpg)
5
... 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
![Page 6: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/6.jpg)
6
The Challenge: Inference Goal: practical type system
polymorphism
def id(x) { return x };1 + id(2);“hello” ^ id(“world”);
polymorphism
id : ∀X. X → X
![Page 7: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/7.jpg)
7
The Challenge: Inference 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}
![Page 8: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/8.jpg)
8
The Challenge: Inference
bounded quantification
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
![Page 9: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/9.jpg)
9
The Challenge: Inference
bounded quantification
Goal: practical type system
subtypingpolymorphism
dynamic
n := if b then 0 else “bad”;m := if b then n + 1 else 0;
dynamic
n : dynamic
![Page 10: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/10.jpg)
10
The Challenge: Inference
bounded quantification
Goal: practical type system
subtypingpolymorphism
dynamicother features...
![Page 11: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/11.jpg)
11
The Challenge: Inference
bounded quantification
Goal: practical type system
subtypingpolymorphism
dynamicother features...
System ML ✓
![Page 12: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/12.jpg)
12
The Challenge: Inference
bounded quantification
Goal: practical type system
subtypingpolymorphism
dynamicother features...
System F ✗
![Page 13: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/13.jpg)
13
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
![Page 14: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/14.jpg)
14
Route: Inference w/ Run-time Logs
bounded quantificationsubtyping+ polymorphism
omit higher-order functions
System E
System E≤
![Page 15: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/15.jpg)
15
First Stop
bounded quantificationsubtyping+ polymorphism
omit higher-order functions
System E
System E≤
System E−
![Page 16: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/16.jpg)
16
• Function definitions
• Function calls
• Program is sequence of function definitions
Typed vs. Untyped Syntax
def y[A1,...,An](x:τ){ e }
def y(x){ e’ }
y[τ1,...,τn](e) y(e’)
![Page 17: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/17.jpg)
17
E− Type System• Expression and function types
τ ::= | Int | Bool | ... | {fi:τi}
| X
σ ::= ∀Xi. τ1 → τ2
• Typing rules prevent field-not-found and primitive operation errors
• No rule for if-expressions yet
![Page 18: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/18.jpg)
18
def id (x) { x }
def id[X] (x:X) { x } : ∀X. X → X
def id[] (x:Int) { x } : Int → Int
def id[Y,Z] (x:Y*Z) { x } : ∀Y,Z. Y*Z → Y*Z
• Infinitely many valid types for id...
![Page 19: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/19.jpg)
19
• ... but ∀X. X → X is the principal type
∀X. X → X
∀Y,Z. Y*Z → Y*ZInt → Int
![Page 20: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/20.jpg)
20
• ... but ∀X. X → X is the principal type
• More general than every other type• Allows id to be used in most different ways
∀Y,Z. Y*Z → Y*Z
∀X. X*X → X*X
Int*Int → Int*IntInt*Bool → Int*Bool
∀X. X → X
Int → Int
![Page 21: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/21.jpg)
21
def readA (x) { x.a }
def readA[A] (x:{a:A}) { x.a } : ∀A. {a:A} → A
• This is the best type
∀A. {a:A} → A
∀A,B. {a:A;b:B} → A{a:Int} → Int
∀B. {a:Int;b:B} → Int
![Page 22: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/22.jpg)
22
def foo (o) { let _ = o.a in o }
• Two valid types:
• Neither is better than the other
∀A. {a:A} → {a:A} ∀A,B. {a:A;b:B} → {a:A;b:B}
allowsfoo({a=1;b=2}).b
allowsfoo({a=1})
![Page 23: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/23.jpg)
23
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
![Page 24: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/24.jpg)
24
τ ::= | Int | Bool | ... | {fi:τi}
| X
Annotated Types
![Page 25: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/25.jpg)
25
“this type variable is for parameter of y and then projected on sequence of fields l”
τ ::= | Int | Bool | ... | {fi:τi}
| Xy.l
Annotated Types
![Page 26: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/26.jpg)
26
def id (x) { x }
τ ::= | Int | Bool | ... | {fi:τi}
| Xy.l
Annotated Types
∀X. X → X
∀Xid. Xid → Xid
![Page 27: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/27.jpg)
27
def readA (x) { x.a }
τ ::= | Int | Bool | ... | {fi:τi}
| Xy.l
Annotated Types
∀A. {a:A} → A
∀XreadA.a. {a:XreadA.a} → XreadA.a
![Page 28: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/28.jpg)
28
def readAB (x) { x.a.b }
τ ::= | Int | Bool | ... | {fi:τi}
| Xy.l
Annotated Types
∀AB. {a:{b:AB}} → AB
∀XreadA.a.b. {a:{b:XreadA.a.b}} → XreadA.a.b
![Page 29: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/29.jpg)
29
τ ::= | Int | Bool | ... | {fi:τi}
| Xy.l
Annotated Types
![Page 30: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/30.jpg)
30
“this record type came from parameter of y andthen projected on sequence of fields l”
τ ::= | Int | Bool | ... | {fi:τi} | {fi:τi}y.l
| Xy.l
Annotated Types
![Page 31: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/31.jpg)
31
def foo (o) { let _ = o.a in o }
Annotated Types
∀A. {a:A} → {a:A}
∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
τ ::= | Int | Bool | ... | {fi:τi} | {fi:τi}y.l
| Xy.l
![Page 32: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/32.jpg)
32
def foo (o) { let _ = o.a in o }
Annotated Types
∀A,B. {a:A;b:B} → {a:A;b:B}
∀Xfoo.a,Xfoo.b. {a:Xfoo.a;b:Xfoo.b} → {a:Xfoo.a;b:Xfoo.b}foo
τ ::= | Int | Bool | ... | {fi:τi} | {fi:τi}y.l
| Xy.l
![Page 33: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/33.jpg)
33
def foo (o) { let _ = o.a in o }
Iterative Inference – Example 1
Iteration 0
Processing foo...
Xfoo <: {a : Xfoo.a}
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
def main () { foo({a=1}) }
![Page 34: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/34.jpg)
34
def foo (o) { let _ = o.a in o } def main () { foo({a=1}) }
Iterative Inference – Example 1
Iteration 0
Processing main...
{a=1} : {a:Int}
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
✓{a:Int} ≤ {a:Xfoo.a} ?
![Page 35: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/35.jpg)
35
def foo (o) { let _ = o.a in o }
Iterative Inference – Example 2
Iteration 0
Processing foo...
Xfoo <: {a : Xfoo.a}
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
def main () { let z = {a=1;b=2} in foo(z).b }
![Page 36: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/36.jpg)
36
def foo (o) { let _ = o.a in o } def main () { let z = {a=1;b=2} in foo(z).b }
Iterative Inference – Example 2
Iteration 0
Processing main...z : {a:Int;b:Int}
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
✓{a:Int;b:Int} ≤ {a:Xfoo.a} ?
![Page 37: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/37.jpg)
37
✗*
def foo (o) { let _ = o.a in o } def main () { let z = {a=1;b=2} in foo(z).b }
Iterative Inference – Example 2
Iteration 0
Processing main...
foo(z) : {a:Int}foo
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
{a:Int}foo ≤ {b:X} ? ✗
Caller-induced constraints
Xfoo <: {b : Xfoo.b}
z : {a:Int;b:Int}
{a:Int;b:Int} ≤ {a:Xfoo.a} ?
![Page 38: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/38.jpg)
38
def foo (o) { let _ = o.a in o } def main () { let z = {a=1;b=2} in foo(z).b }
Iterative Inference – Example 2
Iteration 1
Processing foo...
foo : ∀Xfoo.a. {a:Xfoo.a;b:Xfoo.b} → {a:Xfoo.a;b:Xfoo.b}foo
Xfoo <: {a : Xfoo.a}
Caller-induced constraints
Xfoo <: {b : Xfoo.b}
![Page 39: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/39.jpg)
39
def foo (o) { let _ = o.a in o } def main () { let z = {a=1;b=2} in foo(z).b }
Iterative Inference – Example 2
Iteration 1
foo : ∀Xfoo.a. {a:Xfoo.a;b:Xfoo.b} → {a:Xfoo.a;b:Xfoo.b}foo
Caller-induced constraints
Xfoo <: {b : Xfoo.b}
Processing main...z : {a:Int;b:Int}
✓{a:Int;b:Int} ≤ {a:Xfoo.a;b:Xfoo.b} ?
![Page 40: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/40.jpg)
40
def foo (o) { let _ = o.a in o } def main () { let z = {a=1;b=2} in foo(z).b }
Iterative Inference – Example 2
Iteration 1
foo : ∀Xfoo.a. {a:Xfoo.a;b:Xfoo.b} → {a:Xfoo.a;b:Xfoo.b}foo
Caller-induced constraints
Xfoo <: {b : Xfoo.b}
Processing main...
foo(z) : {a:Int;b:Int}foo
{a:Int;b:Int}foo ≤ {b:X} ?✓
z : {a:Int;b:Int}
{a:Int;b:Int} ≤ {a:Xfoo.a;b:Xfoo.b} ?
![Page 41: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/41.jpg)
41
def main () { let _ = foo({a=1}) in let z = {a=1;b=2} in foo(z).b }
def foo (o) { let _ = o.a in o }
Iterative Inference – Example 3
Iteration 0
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
✓
✓
![Page 42: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/42.jpg)
42
def main () { let _ = foo({a=1}) in let z = {a=1;b=2} in foo(z).b }
def foo (o) { let _ = o.a in o }
Iterative Inference – Example 3
Iteration 0
foo : ∀Xfoo.a. {a:Xfoo.a} → {a:Xfoo.a}foo
✗*
![Page 43: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/43.jpg)
43
Iterative Inference – Example 3
Iteration 1
foo : ∀Xfoo.a. {a:Xfoo.a;b:Xfoo.b} → {a:Xfoo.a;b:Xfoo.b}foo
✗
Calling contexts impose incompatibleconstraints on type of foo
def main () { let _ = foo({a=1}) in let z = {a=1;b=2} in foo(z).b }
def foo (o) { let _ = o.a in o }
![Page 44: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/44.jpg)
44
E− Static Type Inference• In iteration 0, don’t have calling context info
• Iteratively constraint Xfoo as needed
• Process foo and its callers again
• No principal types, but still static inference
• Can run-time information improve algorithm?
![Page 45: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/45.jpg)
45
E− Type Inference with Run-time Logs• Rig evaluation to log caller-induced constraints
1. Wrap all values with sets of type variables
2. When a value passed to function y, add Xy tag
3. When a value with tag Xy.l projected on field f, record Xy.l <: {f : Xy.l.f}
• Iteration 0 of inference looks in log forcaller-induced constraints
![Page 46: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/46.jpg)
46
def foo (o) { let _ = o.a in o } def main () { let z = {a=1;b=2} in foo(z).b }
main()⇒ let z = {a=1;b=2} in foo(z).b⇒ let z = [{a=1;b=2},{}] in foo(z).b⇒ foo([{a=1;b=2},{Xfoo}]).b
⇒ (let _ = [{a=1;b=2},{Xfoo}].a in [{a=1;b=2},{Xfoo}]).b
⇒ (let _ = [1,{Xfoo.a}] in [{a=1;b=2},{Xfoo}]).b
⇒ [{a=1;b=2},{Xfoo}].b
⇒ [2,{Xfoo.b}]
Evaluation
Run-time log
Xfoo <: {b : Xfoo.b}
Xfoo <: {a : Xfoo.a}Caller-inducedconstraint
![Page 47: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/47.jpg)
47
System E− Summary
• Fully static inference needs to iterate
• 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
![Page 48: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/48.jpg)
48
Next Stop
bounded quantificationsubtyping+ polymorphism
System ESystem E
System E≤
System E−
![Page 49: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/49.jpg)
49
E Type System• Type of if-expression is join of branch types
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}
✗
✗
![Page 50: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/50.jpg)
def bar (x,y) { if1 x.n > 0 then x else y }
50
def bar (o) { if1 o.1.n > 0 then o.1 else o.2 }
τ1*τ2 shorthand for {1:τ1;2:τ2}
shorthand for
![Page 51: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/51.jpg)
def bar (x,y) { if1 x.n > 0 then x else y }
• Three valid incomparable types:
51
∀A. {n:Int}*{} → {}
∀A. {n:Int}*{n:Int} → {n:Int}
∀B. {n:Int;b:B}*{n:Int;b:B} →
{n:Int;b:B}
![Page 52: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/52.jpg)
τ ::= | Int | Bool | ... | {fi:τi} | {fi:τi}y.l
| Xy.l
52
New Annotated Types
![Page 53: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/53.jpg)
τ ::= | Int | Bool | ... | {fi:τi} | {fi:τi}y.l | {fi:τi}k.l
| Xy.l
53
“this record type came from if-expression k andthen projected on sequence of fields l”
New Annotated Types
![Page 54: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/54.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
54
![Page 55: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/55.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
Iteration
Constraints from bar
Xbar.1 <: {n : Xbar.1.n}
0
55
New caller-induced constraints from mainType for bar
![Page 56: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/56.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
Iteration
Constraints from bar
Xbar.1.n = Int
0
Xbar.1 <: {n : Xbar.1.n}
56
New caller-induced constraints from mainType for bar
![Page 57: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/57.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
Iteration
Constraints from bar
Xbar.1.n = Int Xbar.1 Xbar.2
Π
0
Xbar.1 <: {n : Xbar.1.n}
57
New caller-induced constraints from mainType for bar
![Page 58: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/58.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
Iteration
Constraints from bar
Xbar.1.n = Int Xbar.1 Xbar.2
Π
0
Xbar.1 <: {n : Xbar.1.n}
58
New caller-induced constraints from mainType for bar
{n:Int} * {} → {}1
![Page 59: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/59.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
Iteration
Constraints from bar
Xbar.1.n = Int Xbar.1 Xbar.2
ΠXbar.1 <: {n : Xbar.1.n}
59
New caller-induced constraints from mainType for bar
{n:Int} * {} → {}1 Xbar.1 <: {n : Xbar.1.n}Xbar.2 <: {n : Xbar.2.n}
0
![Page 60: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/60.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
New caller-induced constraints from mainIteration
Constraints from bar
Type for bar
Xbar.1.n = Int Xbar.1 Xbar.2
Π
{n:Int} * {} → {}1 0
{n:Int} * {n:Int} → {n:Int}1 1
Xbar.1 <: {n : Xbar.1.n}Xbar.2 <: {n : Xbar.2.n}
Xbar.1 <: {b : Xbar.1.b}Xbar.2 <: {b : Xbar.2.b}
Xbar.1 <: {n : Xbar.1.n}
60
![Page 61: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/61.jpg)
def bar (x,y) { if1 x.n > 0 then x else y } def main () { let o = bar({n=1;b=true},{n=2;b=false}) in let _ = o.n + 1 in not o.b }
New caller-induced constraints from mainIteration
Constraints from bar
Type for bar
Xbar.1.n = Int Xbar.1 Xbar.2
Π
{n:Int} * {} → {}1 0
{n:Int} * {n:Int} → {n:Int}1 1
Xbar.1 <: {n : Xbar.1.n}Xbar.2 <: {n : Xbar.2.n}
∀B. {n:Int;b:B} * {n:Int;b:B} → {n:Int;b:B}1
2
Xbar.1 <: {b : Xbar.1.b}Xbar.2 <: {b : Xbar.2.b}
Xbar.1 <: {n : Xbar.1.n}
61
![Page 62: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/62.jpg)
62
System E Summary
• Lacks principal types
• Has iterative inference
• Can run-time info help?– Simple extension to if-expression evaluation– Removes need for iteration, as before
![Page 63: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/63.jpg)
63
Last Stop
bounded quantificationsubtyping+ polymorphism
System E≤System E≤
System E
System E−
![Page 64: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/64.jpg)
64
Bounded Quantification
def y[ A1<:τ1 , ... , An<:τn ] (x:τ) { e }
Type parameters now have bounds
![Page 65: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/65.jpg)
65
def foo (o) { let _ = o.a in o }
• Now there is a best type for foo• Variable X binds all other fields at call sites– X is {a:Int} for foo({a=1})– X is {a:Int;b:Int} for foo({a=1;b=2}).b
65
∀A. {a:A} → {a:A} ∀A,B. {a:A;b:B} → {a:A;b:B}
∀A, X<:{a:A}. X → X
![Page 66: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/66.jpg)
def bar (x,y) { if1 x.n > 0 then x else y }
66
∀Xbar.1<:{n:Int}.
Xbar.1 * Xbar.1 → Xbar.1
{n:Int}*{} → {}
{n:Int}*{n:Int} → {n:Int}
∀B. {n:Int;b:B}*{n:Int;b:B} →
{n:Int;b:B}
![Page 67: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/67.jpg)
def bar (x,y) { if1 x.n > 0 then x else y }
67
∀Xbar.1<:{n:Int}.
Xbar.1 * Xbar.1 → Xbar.1
∀Xbar.1<:{n:Int},Xbar.2<:{}.
Xbar.1 * Xbar.2 → {}
{n:Int}*{} → {}
![Page 68: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/68.jpg)
def bar (x,y) { if1 x.n > 0 then x else y }
68
∀Xbar.1<:{n:Int}.
Xbar.1 * Xbar.1 → Xbar.1
∀Xbar.1<:{n:Int},Xbar.2<:{}.
Xbar.1 * Xbar.2 → {}
allowsbar({n=1},{n=2}).n
allowsbar({n=1},{})
andbar({n=1,b=true},
{n=2,b=false}).b
• Neither type is better
![Page 69: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/69.jpg)
69
Sharing Bounded Type Variables
• E≤ lacks principal types
• Can type variables for x and y be shared?
• If their separate bounds are compatible– X<:{n:Int} and Y<:{} can be combined to {n:Int}– X<:{n:Int} and Y<:{n:Bool} cannot be combined
![Page 70: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/70.jpg)
70
E≤ Inference
• Strategy
1. If possible, use same type variableA. All call sites well-typedB. Otherwise, restart and keep vars separate
2. Otherwise, use separate variables
• Keeping separate variables is just like System E
• Now there is a second cause for restarting
![Page 71: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/71.jpg)
71
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
![Page 72: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/72.jpg)
72
Summary
bounded quantificationsubtyping+ polymorphism
System E≤
System E
System E−
![Page 73: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/73.jpg)
73
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)
![Page 74: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/74.jpg)
74
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
![Page 75: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/75.jpg)
75
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]
![Page 76: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/76.jpg)
76
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
![Page 77: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/77.jpg)
77
Thanks!
Released under Creative Commons Attribution 2.0 Generic LicenseOriginal photo by Alaskan Dude
![Page 78: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/78.jpg)
78
Extra Slides
![Page 79: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/79.jpg)
79
Programs• Program is a sequence of function definitions
def y1[A1,...,An] (x1:τ1) { e1 }
def y2[B1,...,Bm] (x2:τ2) { e2 }
def main[] (z:Unit) { e3 }
• Untyped definitions
def y1 (x1) { e1’ }
![Page 80: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/80.jpg)
80
Programs• Expressions
e ::= | n | b | e1 + e2 | not e | ...
| {fi=ei} | e.f
| y[τ1,...,τn](e)
| if e1 then e2 else e3
| let x = e1 in e2
• Untyped function calls
y(e’)
![Page 81: Type Inference with Run-time Logs](https://reader033.fdocuments.in/reader033/viewer/2022052701/568137ec550346895d9fa02b/html5/thumbnails/81.jpg)
τ ::= | Int | Bool | ... | {fi:τi} | {fi:τi}y.l | {fi:τi}k.l
| Xy.l | Xk.l
81
“this record type came from if-expression k andthen projected on sequence of fields l”
New Annotated Types for E
“this type variable is for if-expression k and then projected on sequence of fields l”