Presentation is loading. Please wait.

Presentation is loading. Please wait.

The Ins and Outs of Gradual Type Inference Avik Chaudhuri Basil Hosmer Adobe Systems Aseem Rastogi Stony Brook University.

Similar presentations


Presentation on theme: "The Ins and Outs of Gradual Type Inference Avik Chaudhuri Basil Hosmer Adobe Systems Aseem Rastogi Stony Brook University."— Presentation transcript:

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


Download ppt "The Ins and Outs of Gradual Type Inference Avik Chaudhuri Basil Hosmer Adobe Systems Aseem Rastogi Stony Brook University."

Similar presentations


Ads by Google