Safe Efficient Gradual Typing for Type Script Aseem

  • Slides: 38
Download presentation
Safe & Efficient Gradual Typing for Type. Script Aseem Rastogi University of Maryland, College

Safe & Efficient Gradual Typing for Type. Script Aseem Rastogi University of Maryland, College Park Nikhil Swamy Cédric Fournet (Microsoft Research) Gavin Bierman (Oracle) Panagiotis Vekris (UCSD)

Gradual Typing Combines benefits of static and dynamic typing Static type errors Performance Typed

Gradual Typing Combines benefits of static and dynamic typing Static type errors Performance Typed interface documentation Dynamic type any Statically-typed fragment Dynamically-typed fragment Rapid prototyping Flexibility Runtime checks mediate interaction 2

Increasing Adoption in Industry Mainly for Java. Script Type. Script, Dart, Closure, Flow (we

Increasing Adoption in Industry Mainly for Java. Script Type. Script, Dart, Closure, Flow (we focus on Type. Script) Increase programmer productivity (static type errors, intellisense, code refactoring, modularity …) Types don’t get in the way of good programmers (retain flavor of programming in Java. Script) 3

Type. Script is Intentionally Unsound For All Its Dynamic Idioms, Typing Java. Script is

Type. Script is Intentionally Unsound For All Its Dynamic Idioms, Typing Java. Script is Hard ! Unsound typing rules to support supposedly common idioms (covariant array subtyping, covariant function arguments, …) Types are uniformly erased during compilation (lightweight compilation, no runtime performance cost, …) (unchecked runtime casts, types don’t guarantee anything) 4

Programmers Cannot Rely On Types private parse. Color. Code (c: string) { if (typeof

Programmers Cannot Rely On Types private parse. Color. Code (c: string) { if (typeof c !== "string") return -1; … } Snippet from Touch. Develop, a large Type. Script Development Tools can’t rely on types Refactoring, compiler optimizations, etc. are not safe 5

Can we design a gradual type system that is: Safe Efficient Supports idiomatic Type.

Can we design a gradual type system that is: Safe Efficient Supports idiomatic Type. Script/Java. Script We present Safe Type. Script 6

Safe Type. Script is Sound Type. Script is Intentionally Unsound Standard variance for arrays

Safe Type. Script is Sound Type. Script is Intentionally Unsound Standard variance for arrays and function arguments Sound treatment of Java. Script this Careful separation of nominal and structural types Easy local rewriting of unsound idioms in 120, 000 line corpus Type. Script has unsound typing rules to support common idioms 7

Safe Type. Script is Sound Type. Script is Intentionally Unsound Safe Type. Script guarantees

Safe Type. Script is Sound Type. Script is Intentionally Unsound Safe Type. Script guarantees type safety Combination of static checking and runtime checks Runtime-type-information (RTTI) based gradual typing Efficiency using two new notions of partial erasure Runtime overhead of only 15% for bootstrapping Safe Type. Script 6. 5% for typed Octane benchmarks Type. Script uniformly erases all types making uses of any unsafe 8

Our Contributions Formalized core of Safe Type. Script, proven sound class C, interface I,

Our Contributions Formalized core of Safe Type. Script, proven sound class C, interface I, {M; F}, number, any, Erased t Implemented in a branch of Type. Script v 0. 9. 5 Can be invoked with --safe command line flag Evaluated on 120, 000 lines of code Bootstrapped Safe Type. Script compiler, New Type. Script compiler, Octane 9

Safe Type. Script Tour Overview of RTTI-based Gradual Typing Values carry Run Time Type

Safe Type. Script Tour Overview of RTTI-based Gradual Typing Values carry Run Time Type Tags consistent with their contents f = 2 g = "s" h = true tag = {f: number; g: string} Object with 3 fields and type tag Dynamically-typed code instrumented to respect RTTI tags Invariant: v : [| v. tag |] 10

RTTI Tagging in Safe Type. Script On-demand Differential interface Point { x: number function

RTTI Tagging in Safe Type. Script On-demand Differential interface Point { x: number function g(p: Point) { p. x = p. x + 1; } function f() { var p: Point = { x = 0 }; g(p); } Safe Type. Script } Compiles unchanged No runtime checks No tagging ! Previous systems tag eagerly Java. Script 11

RTTI Tagging in Safe Type. Script On-demand function g(p: any) { p. x =

RTTI Tagging in Safe Type. Script On-demand function g(p: any) { p. x = p. x + 1; } function f() { var p: Point = { x = 0 }; g(p); } Add RTTI when types lose precision function f() { var p = { x = 0 }; g(shallow. Tag(p, Point)); } shallow. Tag(x, t) = x. tag : = combine(x. tag, t); x Safe Type. Script Java. Script 12

RTTI Tagging in Safe Type. Script Differential interface 2 d. Point extends Point {

RTTI Tagging in Safe Type. Script Differential interface 2 d. Point extends Point { y: number } Add Minimum Required RTTI function h(p: any) {. . } shallow. Tag(x, t) = x. tag : = combine(x. tag, t); x function g(p: Point) { h(p); } function g(p) { h(shallow. Tag(p, Point)); } function f() { var p: 2 d. Point = { x = 0; y = 0 }; g(p); } function f() { var p = { x = 0; y = 0 }; g(shallow. Tag(p, { y: number })); } Safe Type. Script Java. Script 13

RTTI Tagging in Safe Type. Script Add Minimum Required RTTI shallow. Tag(x, t) =

RTTI Tagging in Safe Type. Script Add Minimum Required RTTI shallow. Tag(x, t) = x. tag : = combine(x. tag, t); x function g(p) { h(shallow. Tag(p, Point)); } function f() { var p = { x = 0; y = 0 }; g(shallow. Tag(p, { y: number })); } x = 0 y = 0 Java. Script 14

RTTI Tagging in Safe Type. Script Add Minimum Required RTTI shallow. Tag(x, t) =

RTTI Tagging in Safe Type. Script Add Minimum Required RTTI shallow. Tag(x, t) = x. tag : = combine(x. tag, t); x x = 0 y = 0 tag = {y: number} function g(p) { h(shallow. Tag(p, Point)); } function f() { var p = { x = 0; y = 0 }; g(shallow. Tag(p, { y: number })); } x = 0 y = 0 Java. Script 15

RTTI Tagging in Safe Type. Script x = 0 y = 0 tag =

RTTI Tagging in Safe Type. Script x = 0 y = 0 tag = {x: number; y: number} x = 0 y = 0 tag = {y: number} Add Minimum Required RTTI shallow. Tag(x, t) = x. tag : = combine(x. tag, t); x function g(p) { h(shallow. Tag(p, Point)); } function f() { var p = { x = 0; y = 0 }; g(shallow. Tag(p, { y: number })); } x = 0 y = 0 Java. Script 16

Differential Subtyping Technical Device for On-Demand Differential Tagging Differential Subtyping t 1 <: t

Differential Subtyping Technical Device for On-Demand Differential Tagging Differential Subtyping t 1 <: t 2 ~> d d = 0 | t d is loss in precision that must be captured in the RTTI 17

Differential Subtyping t 1 <: t 2 ~> d d is loss in precision

Differential Subtyping t 1 <: t 2 ~> d d is loss in precision t <: t ~> 0 {x: number; y: number} <: {x: number} ~> {y: number} {x: number; y: number} <: any ~> {x: number; y: number} Primitive RTTI Aware: number <: any ~> 0 18

Differential Subtyping t 1 <: t 2 ~> d d is loss in precision

Differential Subtyping t 1 <: t 2 ~> d d is loss in precision Γ |- e : t 2 ~> e’ t 2 <: t 1 ~> d T-Sub Γ |- e : t 1 ~> shallow. Tag(e’, d) 19

Instrumentation of Dynamically Typed Code function g(p: any) { p. x = "boom"; }

Instrumentation of Dynamically Typed Code function g(p: any) { p. x = "boom"; } function f() { var p: Point = { x = 0 }; g(p); assert(typeof p. x === "number"); } function g(p) { write(p, "x", "boom"); // Fails } function f() {. . } write(o, f, v) = let t = o. tag; o[f] = check(v, t[f]); (Recall that f tags p with type Point) Safe Type. Script Java. Script 20

Differential Tagging Useful, But Not Ideal function g(p: Point) { return p. x; }

Differential Tagging Useful, But Not Ideal function g(p: Point) { return p. x; } function g(p) { return p. x; } Unnecessary shallow. Tag function f() { var p: 2 d. Point = { x = 0; y = 0 }; g(p); } Safe Type. Script function f(p) { var p = { x = 0; y = 0 }; g(shallow. Tag(p, { y: number })); } Java. Script 21

Reason: Need Conservative Tagging Previous gradual type systems: t any for all static types

Reason: Need Conservative Tagging Previous gradual type systems: t any for all static types t Incurs tagging even for statically typed code Relaxing it opens opportunities for sound type erasure 22

Erased Types Programmer-controlled Tagging Behavior A new type modality: Erased t cannot be cast

Erased Types Programmer-controlled Tagging Behavior A new type modality: Erased t cannot be cast to any Statically a t but may not have an RTTI at runtime 23

Subtyping for Erased Types t 1 <: t 2 ~> d t 1 <:

Subtyping for Erased Types t 1 <: t 2 ~> d t 1 <: Erased t 2 ~> 0 Erased t <: any // Zero delta // Ensure full erasure is safe 24

Erased Types Example: No Tagging function g(p: Point) { return p. x; } function

Erased Types Example: No Tagging function g(p: Point) { return p. x; } function g(p) { return p. x; } Unnecessary shallow. Tag function f() { var p: 2 d. Point = { x = 0; y = 0 }; g(p); } Safe Type. Script function f(p) { var p = { x = 0; y = 0 }; g(shallow. Tag(p, { y: number })); } Java. Script 25

Erased Types Example: No Tagging function g(p: Erased Point) { return p. x; }

Erased Types Example: No Tagging function g(p: Erased Point) { return p. x; } function g(p) { return p. x; } function f() { var p: 2 d. Point = { x = 0; y = 0 }; g(p); } function f(p) { var p = { x = 0; y = 0 }; g(p); // No tagging } Safe Type. Script Recall shallow. Tag for non-erased types Java. Script 26

Erased Types Example: No Tagging function h(p: any) {. . } function g(p: Erased

Erased Types Example: No Tagging function h(p: any) {. . } function g(p: Erased Point) { return h(p); } function f() { var p: 2 d. Point = { x = 0; y = 0 }; g(p); } Safe Type. Script Static Type Error function f(p) { var p = { x = 0; y = 0 }; g(p); // No tagging } Java. Script 27

Erased Types Obey a fully static type discipline (Sound type erasure, type abstraction, …)

Erased Types Obey a fully static type discipline (Sound type erasure, type abstraction, …) (Loss in expressiveness: not all code can be turned dynamic) Other advantages of Erased types Working with external libraries that may not have RTTI Adding new features to the type system (e. g. Polymorphism) See our paper for more details 28

Soundness Theorem: Forward Simulation Checks introduced by Safe Type. Script: Catch any dynamic type

Soundness Theorem: Forward Simulation Checks introduced by Safe Type. Script: Catch any dynamic type error Do not alter the semantics of type safe code Tag heap evolution invariant 29

Safe Type. Script Implementation Open Source on Github Implemented in a branch of Type.

Safe Type. Script Implementation Open Source on Github Implemented in a branch of Type. Script v 0. 9. 5 Invoke our type checker with --safe flag 10, 000 Lines of Code Compiles to plain Java. Script (with instrumented checks) (recursive interfaces, inheritance, overloading, generics, arrays, external libs, …) 30

Bootstrapping Safe Type. Script 90, 000 Lines of Code, heavily class based, carefully annotated

Bootstrapping Safe Type. Script 90, 000 Lines of Code, heavily class based, carefully annotated Number of Errors Covariant method arguments 130 Variable scoping 128 Potential unsound use of this 52 Bivariant array subtyping 98 . . . … Total 478 Static Type Errors found in Safe Type. Script Code

Bootstrapping Safe Type. Script 90, 000 Lines of Code, heavily class based, carefully annotated

Bootstrapping Safe Type. Script 90, 000 Lines of Code, heavily class based, carefully annotated All cases in one file using visitor pattern, easily rewritten Sloppy use of var declarations, easily fixed Projection of methods, easily fixed by making them functions Fixed by introducing array mutability qualifiers Number of Errors Covariant method arguments 130 Variable scoping 128 Potential unsound use of this 52 Bivariant array subtyping 98 . . . … Total 478 Static Type Errors found in Safe Type. Script Code

Bootstrapping Safe Type. Script 90, 000 Lines of Code, heavily class based, carefully annotated

Bootstrapping Safe Type. Script 90, 000 Lines of Code, heavily class based, carefully annotated 478 Static type errors 26 failed runtime downcasts; 5 in our own code ! 15% runtime overhead of type safety

Octane Benchmarks (6 / 17) 22 x (ave. ) and 72 x (max. )

Octane Benchmarks (6 / 17) 22 x (ave. ) and 72 x (max. ) overhead with no type annotations Down to 6. 5% after adding type annotations No overhead for statically-typed code Found a variable scoping bug in navier-stokes It has since been fixed Efficiency conditioned on precise type inference Type. Script quite conservative

Also in the paper … Nominal handling of prototype-based classes Sound handling of this

Also in the paper … Nominal handling of prototype-based classes Sound handling of this Abstraction theorem for Erased { } Zero-subtyping to avoid object identity issues More experiments (Type. Script v 1. 1, Octane benchmarks, Different tagging schemes) 35

Safe Type. Script Summary Safe & Efficient Gradual Typing for Type. Script Significant value

Safe Type. Script Summary Safe & Efficient Gradual Typing for Type. Script Significant value for type annotations at a modest cost (runtime checks at least during development and testing) When to use Safe Type. Script ? For mature Type. Script projects, improved code quality Good in development setting for finding early bugs Baseline for JS analyses focusing on deeper properties Give it a go ! 36

Erased Types Example: Type Abstraction interface Point {. . } interface 2 d. Point

Erased Types Example: Type Abstraction interface Point {. . } interface 2 d. Point {. . } function g(p: Point) { (<any> p). y = 3; } function g(p: Point) { write(p, "y", 3); } function f() { var p: 2 d. Point = {x = 0; y = 0}; g(p); } function f() {. . } RTTI of p at write is {y: number} write succeeds: abstraction violation Safe Type. Script Java. Script 37

Erased Types Example: Type Abstraction interface Point extends Erased {. . } interface 2

Erased Types Example: Type Abstraction interface Point extends Erased {. . } interface 2 d. Point extends Point {. . } function g(p: Point) { (<any> p). y = 3; } Static Type Error function f() { var p: 2 d. Point = {x = 0; y = 0}; g(p); } Safe Type. Script Java. Script 38