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 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 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 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