Download presentation
Presentation is loading. Please wait.
Published byFranklin Ryan Modified over 8 years ago
1
The Ins and Outs of Gradual Type Inference Avik Chaudhuri Basil Hosmer Adobe Systems Aseem Rastogi Stony Brook University
2
Gradually Typed Code 2 Dynamically Typed Code missing annotations = dynamic types Dynamically Typed Code missing annotations = dynamic types Statically Typed Code fully annotated with static types Statically Typed Code fully annotated with static types type casts e.g., a Flash application in ActionScript e.g., a Flash application in ActionScript
3
Evolution of Scripts to Programs Dynamically Typed “Script” Dynamically Typed “Script” Statically Typed “Program” Statically Typed “Program” incrementally adding annotations for performance Gradual Typing in our experience, a fantasy missing annotations = dynamic types by default, rather than as fallback
4
Annoying Trade-Off 4 Annotation Burden Performance Penalty Can this trade-off be eliminated?
5
Our Vision of Evolution Process Partially Typed “Script” Partially Typed “Script” Partially Untyped “Program” Partially Untyped “Program” Infer Types Annotate / Restructure Type Inference: Key Ingredient for Evolution
6
Our Contributions 6 Type Inference Algorithm for Gradually Typed Languages Gradual Type Inference Improve Performance of Flash Applications Practical Motivation Backward Compatibility Goal Increase Safety / Eliminate Errors Non Goal … by eliminating as many type casts as possible programs should not break, even when run in arbitrary environments must admit reasoning outside the static type system
7
Gradual Type Inference 7
8
A Gradually Typed Program function foo(n:Number) { var s = 0; var i = s; while(i < n) { s = s + i; i = i + 1; } return s; } 8
9
Gradual Typing: No Type Inference function foo(n:Number):* { var s:* = 0; var i:* = s; while(i < n) { s = s + i; i = i + 1; } return s; } 9 Missing Type = Dynamic Type
10
Gradual Typing: No Type Inference function foo(n:Number):* { var s:* = Number ▷ * 0; var i:* = s; while(i < n) { s = s + i; i = i + 1; } return s; } < : (Number, Number) Boolean + : (Number, Number) Number Type Casts 10 Missing Type = Dynamic Type
11
Gradual Typing: No Type Inference function foo(n:Number):* { var s:* = Number ▷ * 0; var i:* = s; while(* ▷ Number i < n) { s = s + i; i = i + 1; } return s; } < : (Number, Number) Boolean + : (Number, Number) Number 11 Missing Type = Dynamic Type
12
Gradual Typing: No Type Inference function foo(n:Number):* { var s:* = Number ▷ * 0; var i:* = s; while(* ▷ Number i < n) { s = Number ▷ * (* ▷ Number s + * ▷ Number i); i = i + 1; } return s; } < : (Number, Number) Boolean + : (Number, Number) Number 12 Missing Type = Dynamic Type
13
Gradual Typing: No Type Inference function foo(n:Number):* { var s:* = Number ▷ * 0; var i:* = s; while(* ▷ Number i < n) { s = Number ▷ * (* ▷ Number s + * ▷ Number i); i = Number ▷ * (* ▷ Number i + 1); } return s; } < : (Number, Number) Boolean + : (Number, Number) Number 13 Missing Type = Dynamic Type
14
Gradual Typing: No Type Inference function foo(n:Number):* { var s:* = Number ▷ * 0; var i:* = s; while(* ▷ Number i < n) { s = Number ▷ * (* ▷ Number s + * ▷ Number i); i = Number ▷ * (* ▷ Number i + 1); } return s; } Performance Penalty 14 Missing Type = Dynamic Type
15
Gradual Typing: Type Inference function foo(n:Number):Foo! { var s:S = 0; var i:I = s; while(i < n) { s = s + i; i = i + 1; } return s; } 15 Missing Type = Unknown Type Missing Type = Dynamic Type Unknown types represented as type variables, solved to static types where possible, dynamic type as fallback Unknown types represented as type variables, solved to static types where possible, dynamic type as fallback
16
Architecture of Type Inference 16 Program Annotated With Type Variables Program With Coercions Flow Relation Over Types Solutions of Type Variables as Types Compilation Closure Computation Solution Derivation
17
Coercions … are of the form T 1 ▷ T 2 “term of type T 1 flows into context of type T 2 ” T ▷ X is an inflow for type variable X X ▷ T is an outflow for type variable X 17
18
Generating Coercions function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = s; while(i < n) { s = s + i; i = i + 1; } return s; } Number ▷ S 18
19
Generating Coercions function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(i < n) { s = s + i; i = i + 1; } return s; } Number ▷ S S ▷ I 19
20
Generating Coercions function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = s + i; i = i + 1; } return s; } Number ▷ S S ▷ I I ▷ Number 20
21
Generating Coercions function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S> (S ▷ Number s + I ▷ Number i); i = i + 1; } return s; } Number ▷ S I ▷ Number S ▷ I S ▷ Number 21
22
Generating Coercions function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S (S ▷ Number s + I ▷ Number i); i = Number ▷ I (I ▷ Number i + 1); } return s; } Number ▷ S I ▷ Number S ▷ Number S ▷ I Number ▷ I 22
23
Generating Coercions function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S (S ▷ Number s + I ▷ Number i); i = Number ▷ I (I ▷ Number i + 1); } return S ▷ Foo! s; } S ▷ Foo! Number ▷ S I ▷ Number S ▷ Number S ▷ I Number ▷ I 23
24
Solving for Type Variables 24 X X Inflows Outflows
25
Solving in a Static Type System 25 X X Inflows L.U.B. Outflows G.L.B. Solution(X) Precision Safety
26
Solving in a Gradual Type System 26 X X Inflows L.U.B. Solution(X) Precision
27
Solving in a Gradual Type System 27 X X Inflows L.U.B. Solution(X) Recall: eliminating errors is a non-goal Recall: eliminating errors is a non-goal Precision
28
function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S (S ▷ Number s + I ▷ Number i); i = Number ▷ I (I ▷ Number i + 1); } return S ▷ Foo! s; } Solving for Type Variables S = Number S ▷ Foo! Number ▷ S I ▷ Number S ▷ Number S ▷ I Number ▷ I 28
29
function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S (S ▷ Number s + I ▷ Number i); i = Number ▷ I (I ▷ Number i + 1); } return S ▷ Foo! s; } Solving for Type Variables I = Number S = Number S ▷ Foo! Number ▷ S I ▷ Number S ▷ Number S ▷ I Number ▷ I S = Number 29
30
function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S (S ▷ Number s + I ▷ Number i); i = Number ▷ I (I ▷ Number i + 1); } return S ▷ Foo! s; } Solving for Type Variables Foo! = S = Number S ▷ Foo! Number ▷ S I ▷ Number S ▷ Number S ▷ I Number ▷ I I = Number S = Number S = Number 30
31
function foo(n:Number):Foo! { var s:S = Number ▷ S 0; var i:I = S ▷ I s; while(I ▷ Number i < n) { s = Number ▷ S (S ▷ Number s + I ▷ Number i); i = Number ▷ I (I ▷ Number i + 1); } return S ▷ Foo! s; } Solving for Type Variables S ▷ Foo! Number ▷ S I ▷ Number S ▷ Number S ▷ I Number ▷ I I = Number S = Number S = Number Outflows ignored 31 Foo! = S = Number
32
Annotated Program 32 function foo(n:Number):Number { var s:Number = Number ▷ Number 0; var i:Number = Number ▷ Number s; while(Number ▷ Number i < n) { s = Number ▷ Number (Number ▷ Number s + Number ▷ Number i); i = Number ▷ Number (Number ▷ Number i + 1); } return Number ▷ Number s; }
33
Annotated Program: No Casts 33 function foo(n:Number):Number { var s:Number = 0; var i:Number = s; while(i < n) { s = s + i; i = i + 1; } return s; }
34
Summarizing… Key Idea (1) Consider Only Inflows to Solve Type Variables 34
35
Type Inference for Higher Order Types 35 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); }
36
Type Inference for Higher Order Types 36 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); } Boolean Number ▷ X Number Number ▷ X
37
Type Inference for Higher Order Types 37 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); } Boolean Number ▷ X Number Number ▷ X X = ⊥ Number
38
Type Inference for Higher Order Types 38 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); } Boolean Number ▷ X Number Number ▷ X X = ⊥ Number Unsound
39
Type Inference for Higher Order Types 39 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); } Boolean Number ▷ X Number Number ▷ X X = * Number
40
Type Inference for Higher Order Types 40 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); } Boolean Number ▷ X Number Number ▷ X X = * Number Imprecise
41
Type Inference for Higher Order Types 41 var x:X = function(y:Number):Number { … }; If(b) { x = function(y:Boolean):Number { … }; x(true); } X = Boolean Number Boolean Number ▷ X Number Number ▷ X
42
42 Higher Order Types: Kinds
43
43 Suppose that solution of X is of the form _ _ function type Higher Order Types: Kinds
44
44 The kind of X under this structure is X? X! Higher Order Types: Kinds Suppose that solution of X is of the form _ _
45
45 Infer X? and X! based on their inflows function applications of X Higher Order Types: Kinds The kind of X under this structure is X? X! Suppose that solution of X is of the form _ _
46
46 Infer X? and X! based on their Inflows Higher Order Types: Kinds The kind of X under this structure is X? X! Suppose that solution of X is of the form _ _ “a kind for every type constructor” all parts of a higher-order type solved based on inflows ≈ naïve subtyping “a kind for every type constructor” all parts of a higher-order type solved based on inflows ≈ naïve subtyping
47
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } 47 Boolean Number ▷ X Number Number ▷ X Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X Type Inference for Higher Order Types
48
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } 48 Boolean ▷ X? Boolean Number ▷ X Number Number ▷ X Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X Type Inference for Higher Order Types
49
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } X? ▷ Boolean Number ▷ X! 49 Boolean ▷ X? Boolean Number ▷ X Number Number ▷ X Boolean Number ▷ X? X! Type Inference for Higher Order Types Number Number ▷ X? X! X? X! ▷ X
50
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } Number ▷ X! X? ▷ Number 50 X? ▷ Boolean Boolean Number ▷ X Number Number ▷ X Number Number ▷ X? X! Type Inference for Higher Order Types Boolean Number ▷ X? X! Boolean ▷ X? X? X! ▷ X
51
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } 51 Number ▷ X! X? ▷ Number X? ▷ Boolean Boolean ▷ X? Boolean Number ▷ X Number Number ▷ X X? = Boolean Type Inference for Higher Order Types Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X
52
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } X! = Number 52 Number ▷ X! X? ▷ Number Boolean Number ▷ X Number Number ▷ X X? = Boolean Type Inference for Higher Order Types Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X X? ▷ Boolean Boolean ▷ X?
53
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } Solution(X) = L.U.B. of Inflowing Kinds 53 Boolean Number ▷ X Number Number ▷ X X! = Number Type Inference for Higher Order Types X? = Boolean Number ▷ X! X? ▷ Number Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X X? ▷ Boolean Boolean ▷ X?
54
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } X = X? X! Type Inference for Higher Order Types X! = Number X? = Boolean Solution(X) = L.U.B. of Inflowing Kinds Boolean Number ▷ X Number Number ▷ X Number ▷ X! X? ▷ Number Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X X? ▷ Boolean Boolean ▷ X?
55
var x:X = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } Type Inference for Higher Order Types X! = Number X? = Boolean X = Boolean Number Solution(X) = L.U.B. of Inflowing Kinds Boolean Number ▷ X Number Number ▷ X Number ▷ X! X? ▷ Number Boolean Number ▷ X? X! Number Number ▷ X? X! X? X! ▷ X X? ▷ Boolean Boolean ▷ X?
56
var x:Boolean Number = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } 56 Type Inference for Higher Order Types
57
var x:Boolean Number = function(y:Number):Number { … }; if(b) { x = function(y:Boolean):Number { … }; x(true); } 57 Sound More Precise than * Number More Precise than * Number Type Inference for Higher Order Types
58
Summarizing… Key Idea (2) Use Kinds to Infer Higher Order Types 58
59
Public Functions function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(1); 59
60
Public Functions function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(1); Foo? ▷ Number Number ▷ Foo! Number ▷ Foo? Foo! = Number Foo? = Number 60
61
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 61
62
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 62 b = false; foo(true); (External Code)
63
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 63 b = false; foo(true); (External Code) Boolean ▷ * true
64
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 64 b = false; foo(true); (External Code) Boolean ▷ * true ✔
65
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 65 b = false; foo(true); (External Code) Boolean ▷ * true ✔ Boolean ▷ Number true
66
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 66 b = false; foo(true); (External Code) Boolean ▷ * true ✔ Boolean ▷ Number true ✗
67
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 67 b = false; foo(true); (External Code) Boolean ▷ Number true ✗ Unsound ! Boolean ▷ * true ✔
68
Public Functions function foo(x:*):* { if(b) { return x + 1; } else { return 0; } foo(1); function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(1); 68 b = false; foo(true); (External Code) Unsound ! Seeing all inflows is necessary! Boolean ▷ * true ✔ Boolean ▷ Number true ✗
69
Where do we not see all inflows? 69 Type variables in negative positions in the type of the program explicit annotation infer * OR Unsafe to infer
70
Summarizing… Key Idea (3) Seeing All Inflows is Necessary 70
71
Local Functions function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } return foo(y); } 71
72
Local Functions function bar(y:Number):Bar! { function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } return foo(y); } 72
73
Local Functions function bar(y:Number):Bar! { function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } return foo(y); } Sound ! foo can’t be called from External Code 73
74
Local Functions that Escape function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } 74
75
Local Functions that Escape function bar(y:Number):Bar! { function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } 75
76
Local Functions that Escape function bar(y:Number):Bar! { function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Unsound ! b = false; f = bar(1); f(true); (External Code) 76
77
Local Functions that Escape function bar(y:Number):Bar! { function foo(x:Number):Number { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Unsound ! b = false; f = bar(1); f(true); (External Code) 77 Need escape analysis?
78
Local Functions that Escape function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } 78
79
Local Functions that Escape function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } 79 Foo? Foo! ▷ Bar!
80
function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Local Functions that Escape 80 Foo? Foo! ▷ Bar! Foo? Foo! ▷ Bar!? Bar!! Bar!? Bar!! ▷ Bar!
81
function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Local Functions that Escape 81 Bar!? ▷ Foo? Foo! ▷ Bar!! Foo? Foo! ▷ Bar! Foo? Foo! ▷ Bar!? Bar!! Bar!? Bar!! ▷ Bar!
82
function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Local Functions that Escape 82 Bar!? ▷ Foo? Foo! ▷ Bar!! Bar!? is in a negative position in type of program Foo? Foo! ▷ Bar! Foo? Foo! ▷ Bar!? Bar!! Bar!? Bar!! ▷ Bar!
83
function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Local Functions that Escape Bar!? = * 83 Bar!? is in a negative position in type of program Bar!? ▷ Foo? Foo! ▷ Bar!! Foo? Foo! ▷ Bar! Foo? Foo! ▷ Bar!? Bar!! Bar!? Bar!! ▷ Bar!
84
function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Local Functions that Escape Foo? = Bar!? = * ✔ 84 Bar!? = * Bar!? is in a negative position in type of program Bar!? ▷ Foo? Foo! ▷ Bar!! Foo? Foo! ▷ Bar! Foo? Foo! ▷ Bar!? Bar!! Bar!? Bar!! ▷ Bar!
85
function bar(y:Number):Bar! { function foo(x:Foo?):Foo! { if(b) { return x + 1; } else { return 0; } foo(y); return foo; } Local Functions that Escape 85 Foo? = Bar!? = * ✔ Bar!? = * Bar!? is in a negative position in type of program Bar!? ▷ Foo? Foo! ▷ Bar!! Foo? Foo! ▷ Bar! Foo? Foo! ▷ Bar!? Bar!! Bar!? Bar!! ▷ Bar! Foo? = *
86
No Escape Analysis Necessary + are already sufficient 86 Polarity-based restriction on type of program Closure compuation
87
Summarizing… Key Idea (4) Flows Encode Escape Analysis 87
88
Properties of Inference Algorithm Time Complexity: O(N 2 ) (“usually” O(N 3 ) for Languages with Subtyping) Preservation of Runtime Semantics: Programs do not break They can be composed with External Code Proofs for a Calculus of Functions and Objects 88
89
Implementation and Evaluation Implemented the Algorithm for ActionScript Source Language of Flash Applications 89
90
Implementation and Evaluation Implemented the Algorithm for ActionScript Evaluated on V8 and SunSpider Benchmarks 90
91
Implementation and Evaluation ActionScript Compiler (ASC) + ActionScript Virtual Machine (AVM) Partially Typed Code Fully Typed Code Type Inference 91 Only Negative Positions Annotated Manually Annotated
92
Experiments Average 60% Improvement over Partially Typed Recover ~100% Performance of Fully Typed in 13 / 17 Benchmarks Better Than Fully Typed Benchmark 92
93
Experiments Array Reads Object Property Reads Number vs int 93 Range Analysis Improves Performance
94
Things We Did Not Talk About How Do We Tighten Closure Computation? Do We Provide Blame Guarantees? Can Precise Types Decrease Performance? Are the Types We Infer Optimal? 94 See Our Paper !
95
Conclusion Type Inference for Gradually Typed Languages Improve performance of Flash Applications – Infer Precise Static Types for Missing Types – Consider Only Inflows for Solutions – Kinds as Solutions of Higher-Order Types Goal: Backward Compatibility – Polarity-based Restriction on Type of Program – Escape Analysis via Closure Computation 95
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.