RFR: addressing several issues in the implementation of universal tvars [v5]

Maurizio Cimadamore mcimadamore at openjdk.java.net
Mon May 23 09:20:19 UTC 2022


On Mon, 23 May 2022 09:10:10 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

>> src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 1824:
>> 
>>> 1822:                         return true;
>>> 1823:                     }
>>> 1824:                     return (allowUniversalTVars &&
>> 
>> This extra check feels outside the spirit of the rules discussed in https://openjdk.java.net/jeps/8261529.
>> That is, I'd expect type containment to recurse using `isBoundedBy` instead of `isSubtype` (as the first branch of this code does).
>
> I've been doing some scribbling - is the above change required because of code like this:
> 
> 
> static class Box<__universal X> { }
> static primitive class Atom { }
> 
> void test() {
>         Box<? extends Atom> val = null;
>         Box<Atom.ref> ref = null;
>         val = ref; // <------
>  }
>  ```
> 
> With an older compiler I get an error here. Indeed, this `val = ref` conversion cannot be explained in terms of the "isBoundedBy" rule, at least not as defined in the JEP draft:
> 
> Box<Atom.ref> <: Box<? extends Atom>
> --> Atom.ref <= ? extends Atom
> --> Atom.ref is-bounded-by Atom
> 
> But here we hit a roadblock: is-bounded-by doesn't apply in this case:
> 
> 
> We now say that a type S is bounded by a type T if any of the following is true:
> [...]
>     S is a primitive class type whose corresponding reference type is bounded by T; or
> 
> But `S` is not a primitive class type here - only a reference projection of a primitive class type. So this rule doesn't apply and the type containment fails (and hence subtyping fails).
> 
> It seems like the code now rectifies this by trying `isBoundedBy` first and, if that fails, it uses a type conversion instead. But this feels like a big departure, with subtyping now depending on type conversion. If we want to support the above example, then the `isBoundedBy` routine needs to be updated to deal with this - otherwise other places using `isBoundedBy` will fail in a similar way, e.g. well-formedness of generic types:
> 
> 
> class Foo<X extends Atom> { ... }
> 
> Foo<Atom.ref> // is this a legal type?

But, to be clear, we should first make sure that this is the feature we want. IMHO it is not: `Box<? extends Atom>` is a wildcard type that contains only one witness: `Atom`. So, subtyping-wise, I don't think it is ok to conclude that `Box<Atom.ref>` <: `Box<? extends Atom>`, because `Atom.ref` is not in the "span" of the wildcard type on the RHS of the subtyping check.

-------------

PR: https://git.openjdk.java.net/valhalla/pull/684



More information about the valhalla-dev mailing list