Refinement Types for TypeScript
Panagiotis Vekris Benjamin Cosman Ranjit Jhala
University of California, San Diego
PLDI’16 Thursday, June 16 Extensible static analyses for modern scripting languages
2 Extensible static analyses for modern scripting languages
Wide scale Looks like Compiles to
3 Extensible static analyses for modern scripting languages
Wide scale PL Interest Looks like Higher Order Functions Compiles to Object Oriented Optionally Typed Generics
3 Extensible static analyses for modern scripting languages
TS
No runtime Verification Documentation overhead
4 Extensible static analyses for modern scripting languages
Fixed type tests
5 Extensible static analyses for modern scripting languages
Fixed type tests
User specified invariants
5 Extensible static analyses for modern scripting languages
Fixed type tests
User specified invariants
5 Extensible static analyses for modern scripting languages
Fixed type tests
User specified invariants
5 Extensible static analyses for modern scripting languages
Fixed type tests
User specified invariants
5 Example Compute the index of the minimum element of an array
6 7 folds over the elements of an array
7 8 Calls with an appropriate function and initialization
8 Example Compute the index of the minimum element of an array
Verification goal Prove that all array accesses are within bounds
9 Array bounds analysis:
10 Array bounds analysis:
Constraint between two values
11 Array bounds analysis:
Constraint between two values
12 Array bounds analysis:
Constraint between two values
Constraint between value and closure 12 Constraint between value and closure 13 Constraint carries over through call to function parameters
Constraint between value and closure 13 Constraint carries over through call to function parameters
Constraint checked on invocation
14 Constraint carries over through call to function parameters
Constraint checked on invocation
Problem To check array access we must track relations between closures and values
14 Problem To check array access we must track relations between closures and values
Solution Refinement types
14 Refinement Types
Value variable Logical predicate Base type
15 Refinement Types
Value variable Logical predicate Base type
“Set of values of type such that formula is true”
15 Refinement Types
Value variable Logical predicate Base type
“Set of values of type such that formula is true”
E.g.: “Set of valid indexes for an array ”
15 How can we type ?
16 How can we type ?
TypeScript type
16 How can we type ?
TypeScript type Acc
Basic typing offers some guarantees
16 How can we type ?
TypeScript type Acc
Accepts Acc
Basic typing offers some guarantees
16 How can we type ?
TypeScript type Acc
Accepts Acc Returns Acc
Basic typing offers some guarantees
16 How can we type ?
TypeScript type
Does not capture: “valid index of ”
Basic typing offers some guarantees but not value related ones
17 How can we type to account for valid indexes?
TypeScript type
Refinement type
18 How can we type to account for valid indexes?
TypeScript type
Refinement type
18 How can we type to account for valid indexes?
TypeScript type
Refinement type
Captures the relation between closure and value
19 Our contribution Design a refinement type system for TypeScript
20 Challenges
Assignments
Mutability
Overloading
Annotation Overhead
21 Challenges Solutions we used
Assignments SSA Transformation
Mutability Extend type system with immutability guarantees
Overloading Two-phased typing
Annotation Overhead Liquid Types
22 Challenges Solutions we used
Assignments SSA Transformation
Mutability Extend type system with immutability guarantees
Overloading Two-phased typing
Annotation Overhead Liquid Types
23 Assignments
24 25 +
- + - +
+
+
25 What is the type of ?
25 What is the type of ?
Types for
26 What is the type of ?
Types for
27 What is the type of ?
Types for
28 What is the type of ?
Types for
29 Νo single type for
Types for
30 Νο single type for Joining types of causes loss of precision
31 Νο single type for Joining types of causes loss of precision
Use different versions of
31 Use different versions of
32 Use different versions of
Types for
33 Use different versions of
Types for -
34 Each version of has a single precise type & gets assigned once
Types for -
35 Static Single Assignment (SSA)
Types for -
35 Static Single Assignment (SSA)
Types for -
How do we check these types?
35 Reminder
Assignment
generates subtyping constraint
36 Subtyping Constraints
Generated constraints
37 Subtyping Constraints : loop induction variable φ( )
Generated constraints
38 Subtyping Constraints : loop induction variable φ( )
Generated constraints
38 Subtyping Constraints : loop induction variable φ( )
Generated constraints
⊢
39 Subtyping Constraints : loop induction variable φ( )
Loop condition
Generated constraints
⊢
Path Sensitivity
39 Subtyping Constraints
Loop condition
Generated constraints
⊢ ⊢
40 Subtyping Constraints
Safe Array Access
Loop condition
Generated constraints
⊢ ⊢ ⊢
41 Subtyping Constraints
Loop condition
Substitute Generated constraints
⊢ ⊢ ⊢
42 Subtyping Constraints
After substitution
⊢ ⊢ ⊢
43 Subtyping Constraints
Convert to logical implications
⇒ ⇒ ⊢⇒ ⇒ ⊢⇒ ⇒ ⊢⇒ ⇒
44 Subtyping Constraints
Convert to logical implications Solved via SMT
⇒ ⇒ ⊢⇒ ⇒ ⊢⇒ ⇒ ⊢⇒ ⇒
44 Challenges Solutions we used
Assignments SSA Transformation
Mutability Extend type system with immutability guarantees
Overloading Two-phased typing
Annotation Overhead Liquid Types
45 Mutability
46 Why is the access safe?
47 Why is the access safe?
1
is initialized to
47 Why is the access safe?
1 2
is initialized to is bounded by ’s length
47 Why is the access safe?
1 2 3
is initialized to is bounded by ’s length increases only
47 Why is the access safe?
1 2 3 4
is initialized to is bounded by ’s length increases only 4. Length of does not mutate in loop 47 What if array’s length mutates in loop?
48 What if array’s length mutates in loop?
Silently updates
48 What if array’s length mutates in loop? Check becomes stale Silently updates
48 What if array’s length mutates in loop? Check becomes stale Silently updates
Unsafe access!
48 Problem: stale checks break value reasoning Check becomes stale Silently updates
Unsafe access!
49 Extend type system to enforce immutability constraints
50 Literature in Object & Reference Immutability
M. Tschantz and M. D. Ernst. Javari: Adding reference immutability to Java. OOPSLA, 2005.
Y. Zibin, A. Potanin, M. Ali, S. Artzi, A. Kiezun, and M. D. Ernst. Object and Reference Immutability using Java Generics. ESEC/FSE, 2007.
Y. Zibin, A. Potanin, P. Li, M. Ali, and M. D. Ernst. Ownership and Immutability in Generic Java. OOPSLA, 2010.
C. S. Gordon, M. J. Parkinson, J. Parsons, A. Bromfield, and J. Duffy. Uniqueness & Reference Immutability for Safe Parallelism. OOPSLA, 2012.
C. S. Gordon, M. D. Ernst, and D. Grossman. Rely-Guarantee References for Refinement Types over Aliased Mutable Data. PLDI, 2013.
F. Militão, J. Aldrich, and L. Caires. Rely-Guarantee Protocols. ECOOP, 2014.
51 Literature in Object & Reference Immutability
M. Tschantz and M. D. Ernst. Javari: Adding reference immutability to Java. OOPSLA, 2005.
Y. Zibin, A. Potanin, M. Ali, S. Artzi, A. Kiezun, and M. D. Ernst. Object and Reference Immutability using Java Generics. ESEC/FSE, 2007.
Simple extension to type system
Encoded in base types – refinements leverage immutability guarantees
52 Immutability Generic Java [Zibin’07] Mutability as type parameter
53 Immutability Generic Java [Zibin’07] Mutability as type parameter
This can mutate? Others can mutate?
53 Immutability Generic Java [Zibin’07] Mutability as type parameter Only immutable portions in refinement
This can mutate? Others can mutate?
53 Immutability Generic Java [Zibin’07]
54 Immutability Generic Java [Zibin’07]
Call to is flagged as an error, because may only be applied to receivers
54 Challenges Solutions we used
Assignments SSA Transformation
Mutability Extend type system with immutability guarantees
Overloading Two-phased typing
Annotation Overhead Liquid Types
55 Value Based Overloading
56 Value Based Overloading
Function reflects upon and behaves according to types of its arguments
57 Value Based Overloading
Function reflects upon and behaves according to types of its arguments
#args Signature
2
3
57 Value Based Overloading
Function reflects upon and behaves according to types of its arguments
1st behavior – 3 args: is of type
#args Signature
2
3
57 Value Based Overloading
Function reflects upon and behaves according to types of its arguments
2nd behavior – 2 args: is of type
#args Signature
2
3
57 Value Based Overloading
Function reflects upon and behaves according to types of its arguments
Q1: What makes it challenging?
Q2: How pervasive is it?
58 Q1: What makes it challenging?
Type Analysis Value Analysis (base types) (refinements)
59 Q1: What makes it challenging?
Type Analysis Value Analysis (base types) (refinements)
Refinements use invariants established by base types E.g. tracking the access requires to be array
59 Q1: What makes it challenging?
Type Analysis Value Analysis (base types) (refinements)
Refinements use invariants established by base types E.g. tracking the access requires to be array
Type reasoning requires tracking logical relationships E.g. base type of depends on the value of
59 Q1: What makes it challenging?
Type Analysis Value Analysis (base types) (refinements)
Refinements use invariants established by base types E.g. tracking the access requires to be array
Type reasoning requires tracking logical relationships E.g. base type of depends on the value of
Circular dependency complicates formal reasoning & implementation
59 Q2: How pervasive is it?
Study set: DefinitelyTyped: The repository for high quality TypeScript type definitions
60 Q2: How pervasive is it?
Study set: DefinitelyTyped: The repository for high quality TypeScript type definitions
60 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
61 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
61 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Phase 1a. Make clones of body for each overload
61 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Phase 1a. Make clones of body for each overload
61 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Phase 1b. Check body under clone signature
62 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Error: expecting type , passed of type
Value- and path-insensitive type-checking
Phase 1b. Check body under clone signature
62 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Replace errors with , trusting they are indeed dead-code
Phase 1b. Check body under clone signature
63 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Prove dead-code with flow- and path-sensitive analysis
Phase 2. Refinement Type Checking
64 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Signature implies:
Condition makes branch’s environment inconsistent
Prove dead-code with flow- and path-sensitive analysis
Phase 2. Refinement Type Checking
64 How do we check overloaded functions? Two-Phased Typing [ECOOP’15]
Signature implies:
Condition makes branch’s environment inconsistent
Prove dead-code with flow- and path-sensitive analysis
Phase 2. Refinement Type Checking
64 Also in the paper… Scaling to TypeScript • Type features • Array support Object literal types • Interface types Flexible object initialization Primitive types Internal: Constructors Unsound features External: Unique references Undefined & null types Co- & Contra-variant subtyping Unchecked overloads type
65 Also in the paper… Scaling to TypeScript • Type features • Array support Object literal types • Interface types Flexible object initialization Primitive types Internal: Constructors Unsound features External: Unique references Undefined & null types Co- & Contra-variant subtyping Unchecked overloads type
Formal Results Refinement type safety for core language
65 Experimental Evaluation
66 Benchmark suite
File LOC
366 206 304 576 588 189 293 Total 2522
67 Benchmark suite
Octane - NavierStokes: 2D fluid motion simulator File LOC - Splay: splay tree implementation - Richards: OS kernel simulator 366 - Raytrace: ray trace renderer 206 304 576 588 189 293 Total 2522
68 Benchmark suite
Octane - NavierStokes: 2D fluid motion simulator File LOC - Splay: splay tree implementation - Richards: OS kernel simulator 366 - Raytrace: ray trace renderer 206 304 Transducers 576 Composable algorithmic transformations 588 189 293 Total 2522
69 Benchmark suite
Octane - NavierStokes: 2D fluid motion simulator File LOC - Splay: splay tree implementation - Richards: OS kernel simulator 366 - Raytrace: ray trace renderer 206 304 Transducers 576 Composable algorithmic transformations 588 189 293 D3: A JavaScript visualization library - Array operations Total 2522
70 Benchmark suite
Octane - NavierStokes: 2D fluid motion simulator File LOC - Splay: splay tree implementation - Richards: OS kernel simulator 366 - Raytrace: ray trace renderer 206 304 Transducers 576 Composable algorithmic transformations 588 189 293 D3: A JavaScript visualization library - Array operations Total 2522
Microsoft’s TypeScript compiler - Parts of and
71 Annotation Overhead
Annots LOC File (% LOC) 17% 366 24.6 206 9.7 304 27.3 20% 576 14.6 588 27.6 63% 189 26.5 293 23.4 Total 2522 21.4 TypeScript signatures* * Programs need to be fully typed Mutability related – no type in signatures Refinement types
72 Performance
Annots Time LOC File (% LOC) (sec) 366 24.6 473 206 9.7 6 304 27.3 7 576 14.6 15 588 27.6 12 189 26.5 37 293 23.4 62 Total 2522 21.4
73 Performance
Annots Time LOC File (% LOC) (sec) More than 100 static 366 24.6 473 array access sites 206 9.7 6 with dynamically 304 27.3 7 computed indexes 576 14.6 15 588 27.6 12 189 26.5 37 293 23.4 62 Total 2522 21.4
73 Properties Tested
• Property accesses • Array bounds checks • Overloads • Safe Downcasts . Class based . Ad hoc type hierarchies
• User specified value properties. E.g. a function: . returns a positive number . accepts non-empty arrays
74 Properties Tested
Safe Downcasts
Ad hoc type hierarchies
Example taken from:
74 75 TypeScript interfaces are plain JavaScript objects no type information at runtime
75 TypeScript interfaces are plain JavaScript objects no type information at runtime
Explicit field ( ) to encode type info needed for dynamic tests
76 Invariants
77 Invariants
⇒
78 Invariants
⇒
⇒
79 Problem Unchecked invariants
⇒
⇒
80 Problem Unchecked invariants
⇒
⇒
80 Problem Unchecked invariants
⇒
⇒
80 No static or dynamic error
Problem Unchecked invariants
⇒
⇒
81 No static or dynamic error
Problem Unchecked invariants
Solution Encode invariants in refinement types
82 Encode type information in logic
83 Type for accounts for possible sub-interfaces
84 Type for accounts for possible sub-interfaces
⇒
The containing Bitwise AND object
85 Type for accounts for possible sub-interfaces
⇒ Λ ⇒
86 ⇒ Λ ⇒ Λ ⇒ Λ
87 ⇒ Λ ⇒ Λ ⇒ Λ
87 Check downcast
⇒ Λ ⇒ Λ ⇒ Λ
87 Check downcast
Invariant for
⇒ Λ ⇒ Λ ⇒ Λ
88 Check downcast
Invariant for Λ Path condition:
⇒ Λ ⇒ Λ ⇒ Λ
89 Check downcast
Invariant for Path condition: Λ ⇒
⇒ Λ ⇒ Λ ⇒ Λ
90 Encode type information in logic Check downcast
Invariant for Path condition: Λ ⇒
⇒ Λ ⇒ Λ ⇒ Λ
91 Encode type information in logic Check downcast
Invariant for Path condition: Λ ⇒
⇒ Λ ⇒ Λ ⇒ Λ
91 Refinement Types for TypeScript Extensible static analysis for a modern scripting language
Fixed type tests User specified invariants TS
Challenges Solutions Assignments SSA Transformation
Mutability Extend type system with immutability guarantees
Overloading Two-phased typing
Annotation Overhead Liquid Types
Source: Demo: Thanks!
92