Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor John Altidor Taming the Wildcards: Combining Definition- and Use-Site Variance
2 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Outline Motivation for Variance. Existing Approaches. Java only supports use-site variance. C# and Scala only support definition-site variance. What Is New Here: Combine Definition-Site and Use-Site Variance. Both in a single language, each using the other Case Study – Inferring Def-Site for Java. Insights into Formal Reasoning. Summary.
3 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Software Reusability Writing reusable software is hard; many factors: Generality Adaptability Modularity Simplicity of interface / Ease of use … Programming language support Enable reusable code without introducing bugs. Focus on integrating two flavors of genericity: Generics – Parametric Polymorphism Subtyping – Inclusion Polymorphism
4 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Subtyping – Inclusion Polymorphism Example: Java inheritance. class Animal { void speak() { } } class Dog extends Animal { void speak() { print(“bark”); } } class Cat extends Animal { void speak() { print(“meow”); } }
5 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Subtyping – Example Client void performSpeak(Animal animal) { animal.speak(); } Can be a Dog, Cat, or any other Animal.
6 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Common Code Structure class ListOfDogs { void add(Dog num) { … } Dog get(int i) { … } int size() { … } }
7 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Common Code Structure (cont.) class ListOfAnimals { void add(Animal num) { … } Animal get(int i) { … } int size() { … } }
8 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Generics – Parametric Polymorphism class List { void add(X x) { … } X get(int i) { … } int size() { … } } type parameter write X read X no X List ≡ List of Animal s List ≡ List of Dog s Customized Lists
9 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Generics and Subtyping Dog <: Animal (Dog is an Animal). Cat <: Animal (Cat is an Animal). List No! A List can add a Cat to itself. A List cannot.
10 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Variance Introduction When is C a subtype of C ? class RList { X get(int i) { … } int size() { … } } Can read from but not write to. It is safe to assume RList. Why?
11 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Flavors of Variance - Covariance Generic Covariance <: Assuming Dog <: Animal (Dog is an Animal).
12 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Flavors of Variance - Contravariance Generic Contravariance <: Assuming Dog <: Animal (Dog is an Animal).
13 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Four Flavors of Variance How do programmers specify variance? Covariance:T <: U ⇒ C. Contravariance:T <: U ⇒ C. Bivariance: C,for all T and U. Invariance: C,if T <: U and U <: T.
14 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Definition-Site Variance (C#/ Scala) Programmer specifies variance in definition as in Scala and C#. Variance of a type position. Return types: covariant. Arguments types: contravariant. class RList { X get(int i) { … } int size() { … } // no method to add } class WList { void add(X x) { … } int size() { … } // no method to get }
15 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Use-Site Variance (Java Wildcards) class List { void add(X x) { … } X get(int i) { … } int size() { … } }
16 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Use-Site Variance (Java Wildcards) class List { void add(X x) { … } X get(int i) { … } int size() { … } } List
17 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Use-Site Variance (Java Wildcards) class List { void add(X x) { … } X get(int i) { … } int size() { … } } List
18 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Use-Site Variance (Java Wildcards) class List { void add(X x) { … } X get(int i) { … } int size() { … } } List
19 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Definition-Site: Pros Conceptual Simplicity Simpler Type Expressions – no use-site annotations. Subtype policy stated in class definition. Burden on library designers; not on users. Classes declare variance once and for all uses. class RList {... } class WList {... } class List extends RList, WList {... } covariant contravariant invariant
20 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Definition-Site: Cons class RList {... } class WList {... } class List extends RList, WList {... } covariant contravariant invariant Redundant Types scala.collection.immutable.Map scala.collection.mutable.Map Generic with n parameters ⇒ 3 n interfaces (or 4 n if bivariance is allowed)
21 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Use-Site: Pros Flexibility: co-, contra-, bivariant versions on the fly. Easier on library designers Design classes in natural way No need for fractured classes. class List { void add(X x) { … } X get(int i) { … } int size() { … } }
22 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Use-Site Cons: Burden shifts to users of generics. Library designers are often users as well. Type signatures quickly become complicated. Heavy variance annotation required for subtyping. From Apache Commons-Collections Library: Iterator > createEntrySetIterator( Iterator >)
23 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Wildcards Criticism Iterator > createEntrySetIterator( Iterator >) “We simply cannot afford another wildcards” – Joshua Bloch. “Simplifying Java Generics by Eliminating Wildcards” – Howard Lovatt.
24 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Our Approach: Take Best of Both Worlds Take advantages. Remove disadvantages. Simpler type expressions than in Java (burden off clients). Less redundant type definitions in C# and Scala. Inferring definition-site variance from only use-site annotations. [1] Added notion of def-site variance without extending Java. VarLang Calculus: Denotational and language neutral approach. [1] PLDI 2011 (Altidor, Huang, Smaragdakis)
25 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Fewer Wildcard Annotations Iterator > createEntrySetIterator( Iterator >) Iterator > createEntrySetIterator( Iterator >)
26 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor VarLang Calculus Language neutral approach. Simplifies and generalizes all previous work. Sample Applications : Infer definition-site variance for Java. Add use-site variance to C#.
27 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Variance Lattice Ordering details later
28 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Java to VarLang Calculus class C { X foo(C arg1) {... } void bar(D arg2) {... } } class D { void baz(C arg3) {... } } module C { X+, C -, void+, D - } module D { void+, C - }
29 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Infer Definition-Site Variance Def-Site Variance of C = c = +. (C is covariant) Def-Site Variance of D = –. (D is contravariant) module C { X+, C -, void+, D - } module D { void+, C - }
30 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Case Study: Definition-Site Inference for Java How much benefit if Java’s type system inferred definition-site variance? Mapped Java classes to VarLang modules. Applied inference to large, standard libraries e.g., Sun’s JDK 1.6 Example inferences java.util.Iterator is covariant. java.util.Comparator is contravariant.
31 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Sample Results from Case Study Analysis was conservative (e.g. ignored method bodies). “ foo(List arg) ” could have been “ foo(List arg) ”. majority
32 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Insights into Formal Reasoning Variance composition: v 1 ⊗ v 2 = v 3 Variance binary predicate: v( T; T’ ) Variance lattice: v 1 ≤ v 2 Variance of a type: var( X ; T ) Relating variance to subtyping: Subtype Lifting Lemma Variance of a position
33 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Standard Modeling: Variance Lattice Ordered by subtype constraint binary predicate
34 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Variance of a Type When is C a subtype of C ? What about existential types? ∃ X->[ ⊥ -String].Stack We answer a more general question: When is [U/X]T <: [U’/X]T ? Key: defined very general predicate: var( X ; T ) = variance of type T with respect to type variable X.
35 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Subtype Lifting Lemma If: (a) v ≤ var( X ; T ) (b) v( U; U’ ) Then: [U/X]T <: [U’/X]T var( X; Iterator ) = + and + (Dog; Animal) ≡ Dog We generalize Emir et al.’s subtype lifting lemma. Goal property of var.
36 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Variance Composition Variance of variable X in type A >> ? In general, variance of variable X in type C ? v 1 ⊗ v 2 = v 3. If: Variance of variable X in type expression E is v 2. The def-site variance of class C is v 1. Then: variance of X in C is v 3. Transform Operator
37 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Deriving Transform Operator Example Case: + ⊗ – = – Class C is covariant. Type E is contravariant in X. Need to show C is contravariant in X. For any T 1, T 2 : Hence, C is contravariant in X.
38 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Summary of Transform Invariance transforms everything into invariance. Bivariance transforms everything into bivariance. Covariance preserves a variance. Contravariance reverses a variance.
39 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Definition of var predicate Definition-site variance annotations are type checked using var predicate. For further details: [2] ECOOP 2012 (Altidor, Reichenbach, Smaragdakis)
40 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Variance composition: v 1 ⊗ v 2 = v 3 Variance binary predicate: v( T; T’ ) Variance lattice: v 1 ≤ v 2 Variance of a type: var( X ; T ) Relating variance to subtyping: Subtype Lifting Lemma Variance of a position: See [2] for derivation. General Theory – Template for Adding Variance A >> Subtype Policy Comparing Variances Computing Variances Variance Soundness Check Def-Site Variance
41 Taming the Wildcards: Combining Definition- and Use-Site Variance – Altidor Summary of Contributions Generics and subtyping coexist fruitfully. Subtyping between two different instantiations. Combine def-site and use-site variance to reap their advantages and remove disadvantages. Generalize all previous related work. Resolve central questions in the design of any language involving parametric polymorphism and subtyping. Variance of a type. Variance of a position.
To my collaborators: Smaragdakis, Reichenbach, Huang, Palsberg, Tate, Cameron, Kennedy, Urban To CLC for hosting.