Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6801130

JLS3 5.1.10 (capture-conversion) should be clarified

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 7
    • specification
    • None
    • unknown
    • generic

      Consider the following class hierarchy:

      class A{ public void a(){}}
      class B extends A{ public void b(){}}
      interface I{ void i();}
      class E extends B implements I{ public void i(){};}

      class C<W extends B & I, T extends W>{
          public T fieldT; }


      Question: What is the capture of C<? extends I, ? extends E> ?

      It's C<#1. #2>, where both #1 and #2 are captured-type variables. According to JLS3 5.1.10, we have that:

      upper-bound(#1) = glb(I, B&I) = B&I
      upper-bound(#2) = glb(E, #1) = E & #1 (in eval of 6594284 I stated that this glb was incorrect)

      Are #1, #2 conform to declared bounds?

      a) #1 <: B&I, ok (since #1 <: upper-bound(#1) = B&I <: B&I)
      b) #2 <: I, ok (since #2 <: upper-bound(#2) = E&I <: I)

      At first it seems like everything is correct - however reading 5.1.10 it's not crystal clear to understand what the desired behavior should look like:

      "If Ti is a wildcard type argument of the form ? extends Bi, then Si is a fresh type variable whose upper bound is glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. It is a compile-time error if for any two classes (not interfaces) Vi and Vj,Vi is not a subclass of Vj or vice versa"

      I think the problem is all in the sentence *if for any two classes (not interfaces)* ; here we have to compute a glb between a classtype (namely E) and a captured-type-variable (namely #1) - which rules should we apply? This is not clear as #1 is neither a class nor an interface.

      Note: enforcing that either #1 <: E or E <: #1 will result in flagging the above capture-conversion as erroneous as neither of the two subtyping assumptions hold:

      Is either #CAP1 <: E or E <: #CAP1 ?

      a) #1 <: E iff
      ub(#1) = B&I <: E --> false

      b) E <: #1 false

      Note that we don't have (as you say) that #1 = B&I, we have that #1's upper bound is B&I which is different.
      The above subtyping test would hold only if you assume the following rule:

      S <: T iff S <: ub(T)

      which is unsafe (e.g. Integer <: T, where T is a type-variable whose bound is Object).

      I don't see how the subtyping between E and #1 could be justified in term of the JLS.

            abuckley Alex Buckley
            mcimadamore Maurizio Cimadamore
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: