Gradual Typing for Generics

47
Gradual Typing for Generics Lintaro Ina and Atsushi Igarashi Kyoto University 2011-10-26 @ OOPSLA 2011 Lintaro Ina Gradual Typing for Generics 1

Transcript of Gradual Typing for Generics

Gradual Typing for Generics

Lintaro Ina and Atsushi Igarashi

Kyoto University

2011-10-26 @ OOPSLA 2011

Lintaro Ina Gradual Typing for Generics 1

Dynamic vs. Static Typing

•+ flexible

•- unexpectedrun-time errors

•+ reliable

•- tedious to write typeannotations

Lintaro Ina Gradual Typing for Generics 2

Gradual Typing [’06 Siek and Taha]

◮ combines benefits of both sides

◮ Dynamic and static types are both allowed◮ Statically typed part never goes wrong

prototype product release

◮ allows evolutionary development

◮ from flexible scripts◮ to reliable programs

Lintaro Ina Gradual Typing for Generics 3

Recipe for Gradual Typing [1/3]

1 Adding dynamic type dyn

◮ Allow potentially safe code

Lintaro Ina Gradual Typing for Generics 4

Recipe for Gradual Typing [1/3]

1 Adding dynamic type dyn

◮ Allow potentially safe code

dyn x = ...;

x.anyMethod();

String y = x;

y.length();

Lintaro Ina Gradual Typing for Generics 4

Recipe for Gradual Typing [1/3]

1 Adding dynamic type dyn

◮ Allow potentially safe code

dyn x = ...;

x.anyMethod();

String y = x;

y.length();

Lintaro Ina Gradual Typing for Generics 4

Recipe for Gradual Typing [2/3]

2 Translation to an intermediate language

◮ Explicit run-time checks in dyn-parts◮ dyn-free parts do not change

dyn x = ...;

x.anyMethod();

String y = x;

y.length();

Lintaro Ina Gradual Typing for Generics 5

Recipe for Gradual Typing [2/3]

2 Translation to an intermediate language

◮ Explicit run-time checks in dyn-parts◮ dyn-free parts do not change

dyn x = ...;

x.anyMethod();

String y = x;

y.length();

dyn x = ...;

invoke(x, anyMethod);

String y = $String% x;

y.length();

Lintaro Ina Gradual Typing for Generics 5

Recipe for Gradual Typing [3/3]

3 Proof of type safety

◮ Only run-time checks may fail◮ The translation preserves typeability

Lintaro Ina Gradual Typing for Generics 6

Recipe for Gradual Typing

1 Adding dynamic type dyn

◮ Allow potentially safe code

2 Translation to an intermediate language

◮ Explicit run-time checks in dyn-parts◮ dyn-free parts do not change

3 Proof of type safety

◮ Only run-time checks may fail◮ The translation preserves typeability

Lintaro Ina Gradual Typing for Generics 7

Our Goal

A gradual type system for Java

Lintaro Ina Gradual Typing for Generics 8

Our Goal

A gradual type system for Java

Theory

◮ A type system

◮ Proofs of properties

Implementation

◮ A type checker

◮ Byte-code generation for the current JVM

Lintaro Ina Gradual Typing for Generics 8

Our Goal

A gradual type system for Java

Theory

◮ A type system

◮ Proofs of properties

Implementation

◮ A type checker

◮ Byte-code generation for the current JVM

Lintaro Ina Gradual Typing for Generics 8

Issues

◮ Class-based nominal type system

◮ cf. structural type system [’07 Siek and Taha]

◮ Generics

◮ What can we do with List<dyn>?

◮ Matching with the current Java architectures

◮ Each class compiles to a single class file◮ Behavior of statically typed parts

Lintaro Ina Gradual Typing for Generics 9

What We Do and Don’t

Do

◮ Gradual type system for nominal subtyping

◮ Fine-grained integration with generics

◮ Flexible compatibility relation

◮ Ensuring type safety

◮ Bounded dynamic types◮ Run-time checks for parametric types

Don’t

◮ Blame tracking

Lintaro Ina Gradual Typing for Generics 10

What We Do and Don’t

Do

◮ Gradual type system for nominal subtyping

◮ Fine-grained integration with generics

◮ Flexible compatibility relation

◮ Ensuring type safety

◮ Bounded dynamic types◮ Run-time checks for parametric types

Don’t

◮ Blame tracking

Lintaro Ina Gradual Typing for Generics 10

Generics and Dynamic Types

◮ List<dyn> can be used as List<whatever>

◮ You can’t do this in C# 4.0 [’10 Bierman, et al.]

class List<X> { X head; List<X> tail }

List<dyn> ls = ...;

ls.head.anyMethod();

List<String> sls = ls;

Lintaro Ina Gradual Typing for Generics 11

Generics and Dynamic Types

◮ List<dyn> can be used as List<whatever>

◮ You can’t do this in C# 4.0 [’10 Bierman, et al.]

class List<X> { X head; List<X> tail }

List<dyn> ls = ...;

ls.head.anyMethod();

List<String> sls = ls;

◮ How does type checking go?

Lintaro Ina Gradual Typing for Generics 11

Static Compatibility [1/2]

Static Compatibility S . T

S x = ...;

T y = x;

// Is this allowed by the compiler?

◮ Checks whether type S is compatible to type T

◮ Used instead of normal subtype relation <:

Lintaro Ina Gradual Typing for Generics 12

Static Compatibility [2/2]

Static Compatibility S . T

◮ Includes <:

◮ Co- and contra-variant◮ List<String>. List<dyn>◮ List<dyn> . List<String>

are both OK

Lintaro Ina Gradual Typing for Generics 13

Static Compatibility [2/2]

Static Compatibility S . T

◮ Includes <:

◮ Co- and contra-variant◮ List<String>. List<dyn>◮ List<dyn> . List<String>

are both OK

/* the compiler should not reject this */

List<dyn> ls1 = new List<String>(...);

// List<String>. List<dyn>

List<String> ls2 = ls1;

// List<dyn> . List<String>

Lintaro Ina Gradual Typing for Generics 13

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

new NCell<dyn>(new Integer(...)).x.bar();

new NCell<dyn>(new Integer(...)).foo();

new NCell<dyn>("abc").foo();

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

new NCell<dyn>(new Integer(...)).x.bar();

new NCell<dyn>(new Integer(...)).foo();

new NCell<dyn>("abc").foo();

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

new NCell<dyn>(new Integer(...)).x.bar();

new NCell<dyn>(new Integer(...)).foo();

new NCell<dyn>("abc").foo();

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

new NCell<dyn>(new Integer(...)).x.bar();

new NCell<dyn>(new Integer(...)).foo();

new NCell<dyn>("abc").foo(); // reject

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [1/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

new NCell<dyn>(new Integer(...)).x.bar();

new NCell<dyn>(new Integer(...)).foo();

new NCell<dyn>("abc").foo(); // reject

How?

Lintaro Ina Gradual Typing for Generics 14

Bounded Dynamic Types [2/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

// constructor type

NCell<X>:X→ NCell<X>

NCell<dyn>:dyn→ NCell<dyn>

Lintaro Ina Gradual Typing for Generics 15

Bounded Dynamic Types [2/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

// constructor type

NCell<X>:X→ NCell<X>

NCell<dyn>:dyn<Number>→ NCell<dyn<Number>>

Lintaro Ina Gradual Typing for Generics 15

Bounded Dynamic Types [2/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

// constructor type

NCell<X>:X→ NCell<X>

NCell<dyn>:dyn<Number>→ NCell<dyn<Number>>

Bounded Dynamic Type dyn<N>

◮ T . dyn<N> if T <: N◮ T 6. dyn<N> if T 6<: N

Lintaro Ina Gradual Typing for Generics 15

Bounded Dynamic Types [2/2]

class NCell<X extends Number> {

/* in a single NCell.class */

X x; void foo() { this.x.intValue(); } }

// constructor type

NCell<X>:X→ NCell<X>

NCell<dyn>:dyn<Number>→ NCell<dyn<Number>>

Bounded Dynamic Type dyn<N>

◮ T . dyn<N> if T <: N◮ T 6. dyn<N> if T 6<: N

String 6. dyn<Number> (∵ String 6<: Number)

Lintaro Ina Gradual Typing for Generics 15

Run-time checks

List<dyn> ls = new List<Integer>(...);

ls.head.anyMethod();

List<String> sls = ls;

Lintaro Ina Gradual Typing for Generics 16

Run-time checks

◮ Assume List<dyn> as a citizen of thedynamically typed world

List<dyn> ls = new List<Integer>(...);

ls.head.anyMethod();

List<String> sls = ls;

Lintaro Ina Gradual Typing for Generics 16

Run-time checks

◮ Assume List<dyn> as a citizen of thedynamically typed world

List<dyn> ls = $List<dyn>% new List...;

invoke(ls.head, anyMethod);

List<String> sls = $List<String>% ls;

Lintaro Ina Gradual Typing for Generics 16

Run-time checks

◮ Assume List<dyn> as a citizen of thedynamically typed world

List<dyn> ls = $List<dyn>% new List...;

invoke(ls.head, anyMethod);

List<String> sls = $List<String>% ls;

◮ When does $T% e succeed?

Lintaro Ina Gradual Typing for Generics 16

Run-time Compatibility [1/2]

Run-time Compatibility S :≺ T

$T% new S(...);

// Does this succeed at run time?

◮ Checks whether a value of S is compatible to T

◮ Used instead of normal subtype relation <:

Lintaro Ina Gradual Typing for Generics 17

Run-time Compatibility [2/2]

Run-time Compatibility S :≺ T

◮ Includes <:◮ Co-variant but not contra-variant

◮ List<String> :≺ List<dyn>◮ List<dyn> 6 :≺ List<String>

Lintaro Ina Gradual Typing for Generics 18

Run-time Compatibility [2/2]

Run-time Compatibility S :≺ T

◮ Includes <:◮ Co-variant but not contra-variant

◮ List<String> :≺ List<dyn>◮ List<dyn> 6 :≺ List<String>

List<dyn> ls1 = new List<dyn>(...);

ls1.head = new Integer(1);

List<String> ls2 = ls1;

ls2.head.length();

Lintaro Ina Gradual Typing for Generics 18

Run-time Compatibility [2/2]

Run-time Compatibility S :≺ T

◮ Includes <:◮ Co-variant but not contra-variant

◮ List<String> :≺ List<dyn>◮ List<dyn> 6 :≺ List<String>

List<dyn> ls1 = new List<dyn>(...);

ls1.head = new Integer(1);

List<String> ls2 = ls1;

ls2.head.length(); /* should not fail

because it’s statically typed */Lintaro Ina Gradual Typing for Generics 18

Run-time Compatibility [2/2]

Run-time Compatibility S :≺ T

◮ Includes <:◮ Co-variant but not contra-variant

◮ List<String> :≺ List<dyn>◮ List<dyn> 6 :≺ List<String>

List<dyn> ls1 = new List<dyn>(...);

ls1.head = new Integer(1);

List<String> ls2 = ls1; /* run-time error

List<dyn> 6:≺ List<String> */

ls2.head.length(); // this does not execute

Lintaro Ina Gradual Typing for Generics 18

Formalization

◮ Extend Featherweight GJ (FGJ) with dyn

◮ Give a translation to an intermediate language

◮ . and :≺ instead of normal subtyping <:

Surface language Intermediate languageFGJ + dyn FGJ + dyn + run-time checkscompatibility . compatibility :≺

typing (typing)reduction

Lintaro Ina Gradual Typing for Generics 19

Compatibility Relations

Auxiliary Relation S ≺ T

◮ In S, dyns in T are replaced with non-dyns

∆ ⊢ T ≺ T∆ ⊢ S ≺ T

∆ ⊢ C<S> ≺ C<T>

∆ ⊢ T <: S ∆ ⊢ S ≺ N

∆ ⊢ T ≺ dyn<N>

Definitions

◮ Static compatibility S . Tdef

= S ≻ ∃U <: ∃V ≺ T

◮ Run-time compatibility S :≺ Tdef

= S <: ∃U ≺ T

Lintaro Ina Gradual Typing for Generics 20

Properties

Weak Type Safety in the Intermediate LanguageAn execution of a program of type T

1 results in a value of type S ( :≺ T), or

2 results in a failure of a run-time check, or

3 does not stop

Translation from the Surface to the IntermediateA well-typed program can translate and

◮ typeability is preserved

◮ statically typed parts do not change

Lintaro Ina Gradual Typing for Generics 21

Conclusions

◮ Gradual typing for class-based languages

◮ Fine-grained integration with generics

◮ Static and run-time compatibility◮ Bounded dynamic types

◮ Formalization

◮ FGJ + dyn + run-time checks◮ Type safety and translation theorem

Lintaro Ina Gradual Typing for Generics 22

Future Work

◮ Decidability of . and :≺

:≺ decidable?. at least semidecidable?

◮ Full compiler with a large scale evaluation

◮ Integration with method overloading,wildcards, etc.

◮ Blame tracking instead of run-timecompatibility checks

Lintaro Ina Gradual Typing for Generics 23

THANK YOU!