Caco-2 cell permeability assay for drug absorption
Gradual Typing for Generics
1. Gradual Typing for Generics
Lintaro Ina and Atsushi Igarashi
Kyoto University
2011-10-26 @ OOPSLA 2011
Lintaro Ina Gradual Typing for Generics 1
2. Dynamic vs. Static Typing
•+ flexible
•- unexpected
run-time errors
•+ reliable
•- tedious to write type
annotations
Lintaro Ina Gradual Typing for Generics 2
3. 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
4. Recipe for Gradual Typing [1/3]
1 Adding dynamic type dyn
◮ Allow potentially safe code
Lintaro Ina Gradual Typing for Generics 4
5. 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
6. 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
7. 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
8. 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
9. 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
10. 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
11. Our Goal
A gradual type system for Java
Lintaro Ina Gradual Typing for Generics 8
12. 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
13. 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
14. 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
15. 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
16. 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
17. 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
18. 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
19. 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
20. 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
21. 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
22. 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
23. 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
24. 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
25. 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
26. 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
27. 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
28. 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
29. 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
30. 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
31. 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 dyn<N> if T <: N
Lintaro Ina Gradual Typing for Generics 15
32. 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 dyn<N> if T <: N
String dyn<Number> (∵ String <: Number)
Lintaro Ina Gradual Typing for Generics 15
33. Run-time checks
List<dyn> ls = new List<Integer>(...);
ls.head.anyMethod();
List<String> sls = ls;
Lintaro Ina Gradual Typing for Generics 16
34. Run-time checks
◮ Assume List<dyn> as a citizen of the
dynamically typed world
List<dyn> ls = new List<Integer>(...);
ls.head.anyMethod();
List<String> sls = ls;
Lintaro Ina Gradual Typing for Generics 16
35. Run-time checks
◮ Assume List<dyn> as a citizen of the
dynamically 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
36. Run-time checks
◮ Assume List<dyn> as a citizen of the
dynamically 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
37. 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
38. Run-time Compatibility [2/2]
Run-time Compatibility S :≺ T
◮ Includes <:
◮ Co-variant but not contra-variant
◮ List<String> :≺ List<dyn>
◮ List<dyn> :≺ List<String>
Lintaro Ina Gradual Typing for Generics 18
39. Run-time Compatibility [2/2]
Run-time Compatibility S :≺ T
◮ Includes <:
◮ Co-variant but not contra-variant
◮ List<String> :≺ List<dyn>
◮ List<dyn> :≺ 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
40. Run-time Compatibility [2/2]
Run-time Compatibility S :≺ T
◮ Includes <:
◮ Co-variant but not contra-variant
◮ List<String> :≺ List<dyn>
◮ List<dyn> :≺ 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
41. Run-time Compatibility [2/2]
Run-time Compatibility S :≺ T
◮ Includes <:
◮ Co-variant but not contra-variant
◮ List<String> :≺ List<dyn>
◮ List<dyn> :≺ List<String>
List<dyn> ls1 = new List<dyn>(...);
ls1.head = new Integer(1);
List<String> ls2 = ls1; /* run-time error
List<dyn> :≺ List<String> */
ls2.head.length(); // this does not execute
Lintaro Ina Gradual Typing for Generics 18
42. Formalization
◮ Extend Featherweight GJ (FGJ) with dyn
◮ Give a translation to an intermediate language
◮ and :≺ instead of normal subtyping <:
Surface language Intermediate language
FGJ + dyn FGJ + dyn + run-time checks
compatibility compatibility :≺
typing (typing)
reduction
Lintaro Ina Gradual Typing for Generics 19
43. 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 T
def
= S ≻ ∃
U <: ∃
V ≺ T
◮ Run-time compatibility S :≺ T
def
= S <: ∃
U ≺ T
Lintaro Ina Gradual Typing for Generics 20
44. Properties
Weak Type Safety in the Intermediate Language
An 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 Intermediate
A well-typed program can translate and
◮ typeability is preserved
◮ statically typed parts do not change
Lintaro Ina Gradual Typing for Generics 21
45. 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
46. 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-time
compatibility checks
Lintaro Ina Gradual Typing for Generics 23