Does JLS tell if this program is legal?

Dan Smith daniel.smith at oracle.com
Thu May 23 14:52:21 UTC 2024


> On May 23, 2024, at 3:19 AM, Stephan Herrmann <stephan.herrmann at berlin.de> wrote:
> 
> Thanks, Dan,
> 
> Am 22.05.24 um 02:13 schrieb Dan Smith:
>>> On May 21, 2024, at 12:49 PM, Stephan Herrmann <stephan.herrmann at berlin.de> wrote:
>>> 
>>> * Super<Inner<?>> is a supertype of T / One<?> (directly)
>> Note that "is a supertype" here isn't true though:
>> Is One<?> <: Super<Inner<?>>
>> Is One<CAP> <: Super<Inner<?>>
>> Is Super<Inner<CAP>> <: Super<Inner<?>>
>> Is Inner<CAP> = Inner<?>
>> false
> 
> Wow, another corner I hadn't yet looked at. :) I had assumed that capture applies only when something is being accessed / evaluated. Going from a type to its supertype didn't look like evaluation to me.
> 
> But now looking at §4.10.2 I see it speaking of capture indeed.
> 
> So that would change my analysis
> from Super<Inner<?>> is a supertype of T / One<?>
> to   Super<Inner<CAP>> is a supertype of T / One<?>
> 
> and we continue:
> * S1 = Inner<X>
> * T1 = Inner<CAP>
> * new constraint formula created: ⟨Inner<X> = Inner<CAP>⟩
> 
> This, too, reduces to false, and again I would be without an explanation how 'accept' could be correct.

No, I'm not saying you should use capture to find a supertype.

I'm saying your proposed supertype, Super<Inner<?>>, is demonstrably not a supertype of One<?>, by following the normal subtyping rules. And, it turns out, neither is Super<Inner<CAP>>.

(So what *is* the supertype? Well, yeah, that's the spec bug. It's not defined.)

> 
>> This is related to
>> https://bugs.openjdk.org/browse/JDK-8016196
>> Unfortunately, JLS doesn't specify a way to map from subtypes to supertypes when wildcards are involved. (It's one of those unexplained corners of the type system.)
> 
> Isn't that given by that sentence I discovered just now?
> 	"Given a generic class or interface C with type parameters F1,...,Fn (n > 0), the direct supertypes of the parameterized type C<R1,...,Rn> where at least one of the Ri (1 ≤ i ≤ n) is a wildcard type argument, are the direct supertypes of the parameterized type C<X1,...,Xn> which is the result of applying capture conversion to C<R1,...,Rn> (§5.1.10)."

That is a thing the spec says, but... it's not true. Clearly, following normal subtyping rules, One<?> is not a subtype Super<Inner<X>> for any type variable X.

>> I've got a solution in my mind that involves the upward projection operation we introduced in 4.10.5: capture, find the supertype, then project away the capture variable. But there are details to work out.
> 
> If I apply this strategy in ecj I get these pairs of supertypes of One<?> , Y
> * One<?>, One<X>
> * Super<? extends Inner<?>>, Super<Inner<X>>
> 
> In both pairs we find a wildcard as a direct type argument and hence NO new constraint would be generated in §18.3.1.
> 
> Is that what you have in mind?

Right. It is true, per the subtyping rules, that

One<?> <: Super<? extends Inner<?>>

> Does javac already implement this application of projection?

No, I don't believe so. The bug remains, it's something that needs to be addressed sometime.



More information about the compiler-dev mailing list