510 likes | 526 Views
Towards a Semantic Model for Java Wildcards. Sophia Drossopoulou. Nicholas Cameron. Alexander J. Summers. ETH Zurich Zürich. Victoria Univ. of Wellington New Zealand. Mariangiola Dezani-Ciancaglini. Università di Torino Italy. Imperial College London. Outline.
E N D
Towards a Semantic Model for Java Wildcards Sophia Drossopoulou Nicholas Cameron Alexander J. Summers ETH Zurich Zürich Victoria Univ. of Wellington New Zealand Mariangiola Dezani-Ciancaglini Università di Torino Italy Imperial College London
Outline • Java Wildcards & Existential Types • Semantic Model for Existential Types • Soundness & (In-)Completeness • Weak Independence & Completeness • Conclusions
Outline • Java Wildcards & Existential Types • Semantic Model for Existential Types • Soundness & (In-)Completeness • Weak Independence & Completeness • Conclusions
Wildcards in Java • Based on Java Generics (since Java 5.0) • Parameterised types : List<X>, List<List<String>>, etc. • Generic types are subtype invariant • List<String> and List<Object> are incomparable • Wildcards introduce “hiding” of type parameters • List<?> is a type (a List of “something”) • List<Object> subtype of List<?> • List<String> subtype of List<?> • Bounded wildcards allow subtype variance • List<? extends String> subtype of List<? extends Object> • List<? super Object> subtype of List<? super String>
Existential Types • Existential types allow type information to be hidden • Bounded existentials expose some information about hidden type, e.g., X:[String Object].C<X> • Standard representation of wildcard types • C<?> represented by X:[ Object].C<X> • C<? super B>represented byX:[B Object].C<X> • For Java, introduction and elimination of existential types is handled implicitly (by subtyping). • Java has f-bounded types (type variables may occur in each other’s bounds, mutually)
Why use Existential Types? • Not all types that can occur during type checking of Java programs can be written using the Java syntax • i.e., there are types that are expressible but not denotable in Java • Not true for existential types • All Java types can be denoted using existential types • e.g., X.Pair<X, X> can arise during type-checking (but Pair<?,?>corresponds to X,Y.Pair<X, Y>)
Syntactic Type Assignment • Types and type environments are defined by:Class types N ::= C < T >types T ::= X | ∃Δ.Ntype bounds B ::= T | ⊥type environments Δ ::= X : [B B] • We use σfor type substitutions, and use a judgement Δ ⊢ σ to express that σ maps the type variables in Δ to types within their declared bounds • Syntactic subtypingΔ⊢ T1≤ T2 handles subclassing, existential types and their bounds • e.g.,Δ, Δ1 ⊢ σ ⇒Δ ⊢ σ(N) ≤ ∃Δ1.N
Outline • Java Wildcards & Existential Types • Semantic Model for Existential Types • Soundness & (In-)Completeness • Weak Independence & Completeness • Conclusions
Our semantics for types • Idea: interpret existential types as unions • all the possible concrete types the existential might “hide” • What are “concrete types”? • One idea: use structural types to describe fields and methods guaranteed to exist in the runtime object • but Java uses a nominal type system • allows use of fields and methods based only on class type • Each runtime object has an associated closed class type • We use these as the “concrete types” of our model
Our semantics for types • Semantic types S are sets of closed class types • all the possible runtime types the type might permit • We give a semantic interpretation of closed types • open types will be dealt with later • We map closed types to semantic types as follows: [[ N ]] = { N’| N’⊑ N } [[ ⊥ ]] = ∅ [[ ∃Δ.N ]] = Uσ with Δ ⊢ σ[[ σ(N) ]]
Our semantics for types [[ N ]] = { N’| N’⊑ N } [[ ⊥ ]] = ∅ [[ ∃Δ.N ]] = Uσ with Δ ⊢ σ[[ σ(N) ]] • For example... • [[ Object ]] = { Object, String, List<Object>, … } • [[∃X : [String Object], ∃Y : [X Object].Pair<X,Y> ]] = • { Pair<String,String>, Pair<String,Object>, Pair<Object,Object> }
Semantic subtyping • We define subtyping on semantic types simply as S1≤ S2 ⇔ S1 ⊆ S2 • We extend this notion to syntactic types, as follows:Δ⊨ T1≤ T2 ⇔ ∀ σ, Δ ⊢ σ⇒ [[ σ(T1) ]] ⊆ [[ σ(T2) ]] • We now have two subtyping judgements: syntactic Δ⊢ T1≤ T2 and semantic subtypingΔ⊨ T1≤ T2 • Is syntactic subtyping sound? Δ⊢ T1≤ T2⇒ Δ⊨ T1≤ T2 ? • Is syntactic subtyping complete? Δ⊢ T1≤ T2⇐ Δ ⊨ T1≤ T2 ?
Outline • Java Wildcards & Existential Types • Semantic Model for Existential Types • Soundness & (In-)Completeness • Weak Independence & Completeness • Conclusions
Soundness • Since type soundness for Java Wildcards is known [Cameron et al. 2008] we would hope that soundness of subtyping holds. • In fact, we proved this (Theorem 1 in paper): Soundness: Δ⊢ T1≤ T2⇒ Δ⊨ T1≤ T2 • By defining a suitable semantic type assignment we extended the soundness result to the type system • Completeness could be reasonably expected: • result w.r.t. nominal subtyping (weaker than structural) • decidability of the syntactic type system is open • However, completeness turns out not to hold
Incompleteness 1 • Consider the type ∃X : [C C].List<X> • The semantic model “knows” that X must hide C : • [[∃X : [C C].List<X>]] = {List<C>} = [[List<C>]] • In particular, ⊨ ∃X : [C C].List<X>≤ List<C> holds • This subtyping cannot be derived syntactically • syntactic rules cannot identify the “uniqueness” of X • What if we add a rule specifically for such cases? Δ ⊢U≤ B Δ ⊢B≤ U (eq) Δ⊢∃X : [B U].N ≤ N{B/X}
Incompleteness 2 • This is still not enough. Consider now the typesT1 = ∃X : [⊥ Y], ∃Y : [X Object].Pair<X,Y> T2 = ∃Z : [⊥ Object].Pair<Z,Z> • The bounds on X and Y can only be satisfied if the same (closed class) type is chosen to replace each • the model shows this: [[ T1 ]] = [[ T2 ]] • In particular, ⊨ T1≤ T2 holds, but not syntactically • Further examples make completeness unfeasible • But, could we find a restricted type language for which completeness does hold?
Outline • Java Wildcards & Existential Types • Semantic Model for Existential Types • Soundness & (In-)Completeness • Weak Independence & Completeness • Conclusions
Completeness? When does Δ⊨ T1≤ T2⇒ Δ ⊢ T1≤ T2 hold ?
Completeness? When does Δ⊨ T1≤ T2⇒ Δ ⊢ T1≤ T2hold ?
Completeness? When does Δ⊨ T1≤ T2⇒ Δ⊢ T1≤ T2hold ?
Completeness? ⊨ ∃Δ1.N1≤ ∃Δ2.N2⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2?
Completeness? ⊨ ∃Δ1.N1≤ ∃Δ2.N2⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2? [[ ∃Δ1.N1 ]] ⊆ [[ ∃Δ2.N2 ]] ⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2? Uσ1 with Δ1⊢ σ1[[ σ1(N1) ]] ⊆ Uσ2 with Δ2 ⊢ σ2[[ σ2(N2) ]] ⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2 ? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2 ?
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2 ?
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ?
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ?
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢σ2such that σ1(N1)=σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢σ2such that σ1(N1)=σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢σ2such that σ1(N1)=σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢σ1 there exists σ2withΔ2⊢σ2such that σ1(N1)=σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y = Y X X
Completeness? X X (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y = Y X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ ? Y = Y X X X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ there exists σ3withΔ2⊢σ3such that N1= σ3(N2) Y = Y X X X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ there exists σ3withΔ2⊢σ3such that N1= σ3(N2) ⇒ ⊢ ∃Δ1.N1≤ ∃Δ2.N2 Y = Y X X X X
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ there exists σ3withΔ2⊢ σ3such that N1= σ3(N2) • The red property below is sufficient to deduce completeness (Δ1 is “rich” in the language of paper) • Previous pictures suggest it is enough for there to be “sufficiently different” instantiations for Δ1 • This is not quite enough, with multiple variables • e.g., Δ1= X : [⊥ C], Y : [X X] and Δ2= Z : [⊥ C] and N1= Pair<X,Y> and N2= Pair<Z,Z>
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇒ there exists σ3withΔ2⊢ σ3such that N1= σ3(N2) • The red property below is sufficient to deduce completeness (Δ1 is “rich” in the language of paper) • Previous pictures suggest it is enough for there to be “sufficiently different” instantiations for Δ1 • This is not quite enough, with multiple variables • e.g., Δ1= X : [⊥ C], Y : [X X] and Δ2= Z : [⊥ C] and N1= Pair<X,Y> and N2= Pair<Z,Z>
Completeness? (forallσ1withΔ1⊢ σ1 there exists σ2withΔ2⊢ σ2such that σ1(N1)= σ2(N2)) ⇏ there exists σ3withΔ2⊢ σ3such that N1= σ3(N2) • The red property below is sufficient to deduce completeness (Δ1 is “rich” in the language of paper) • Previous pictures suggest it is enough for there to be “sufficiently different” instantiations for Δ1 • This is not quite enough, with multiple variables • e.g., Δ1= X : [⊥ C], Y : [X X] and Δ2= Z : [⊥ C] and N1= Pair<X,Y> and N2= Pair<Z,Z>
Completeness? • The red property below is sufficient to deduce completeness (Δ1 is “rich” in the language of paper) • Previous pictures suggest it is enough for there to be “sufficiently different” instantiations for Δ1 • This is not quite enough, with multiple variables • e.g., Δ1= X : [⊥ C], Y : [X X] and Δ2= Z : [⊥ C] and N1= Pair<X,Y> and N2= Pair<Z,Z> • We need that each variable in Δ1 gets sufficiently varied instantiations independently of the others...
Weak Independence • We define two types to be sufficiently different if the uppermost class types in their structure differ • We say Δ1 is weakly independent if for each variable X in Δ1 there exist two substitutions σ1, σ2such that σ1(X) is sufficiently different from σ2(X) and for all other variables Y inΔ1 ,σ1(Y) = σ2(Y) • Essentially, each variable gets the chance to vary independently of the others • e.g., X : [⊥ C], Y : [X X]is not weakly independent, but X : [String Object], Y : [X Object]is
Weak Completeness • We proved a weak completeness result: If ⊨ ∃Δ1.N1≤ ∃Δ2.N2 and Δ1 is weakly independent, then ⊢ ∃Δ1.N1≤ ∃Δ2.N2 • Recall: all types can be written in the form ∃Δ.N(in which Δ is possibly empty) – this is not a restriction • The result does not apply (yet) to open types (those featuring type parameters of the enclosing class) • However, for closed types with weakly independent environments, syntactic subtyping is sound and complete with respect to our semantic model
Conclusions and Future Work • Defined a semantic model for Java Wildcards • Proved soundness of Java subtyping w.r.t. model • Completeness does not hold in general • Identified a restriction (weakly-independent environments) under which completeness holds • For future work, open types should be handled • Can we find a weaker restriction for completeness? • Can non-trivial incompleteness arise in Java? • we conjecture not, which would give us strong soundness and completeness results for Java subtyping