RFR: 8322810: Lambda expression types can't be classes [v7]
Maurizio Cimadamore
mcimadamore at openjdk.org
Fri Apr 11 08:32:33 UTC 2025
On Fri, 11 Apr 2025 00:43:02 GMT, Vicente Romero <vromero at openjdk.org> wrote:
>> Currently javac is accepting code like:
>>
>>
>> class Test {
>> void m() {
>> var r = (Test & Runnable) () -> System.out.println("Hello, World!");
>> }
>> }
>>
>>
>> according to: `4.9 Intersection Types` a notional interface can't be induced here as one of the components is a class different from `j.l.Object`
>>
>> With this fix this code pattern will be rejected with a compiler error
>>
>> TIA
>
> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision:
>
> additional tests
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 3346:
> 3344: }
> 3345: }
> 3346: if (bound.tsym != syms.objectType.tsym && (!bound.isInterface() || (bound.tsym.flags() & ANNOTATION) != 0)) {
One question: we currently check this condition in `Types.findDescriptorInternal`. That method has this check:
if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0 || origin.isSealed()) {
//t must be an interface
throw failure("not.a.functional.intf", origin);
}
Where this goes wrong (I think) is that if `origin` is an intersection type, this check fails, because it doesn't recursively check all the components of the intersection. But that would be easy to fix -- e.g. by having a special guard for intersection types.
Digging deeper, the real issue seems to be in how we compute a notional type for the intersection type. The JLS says this (4.9):
> If Ck is Object, a notional interface is induced; otherwise, a notional class is induced with direct superclass type Ck. This class or interface has direct superinterface types T1', ..., Tn' and is declared in the package in which the intersection type appears.
This means that the notional type we create in `Attr.targetChecker` should NOT blindly do this:
notionalIntf.tsym.flags_field |= INTERFACE;
Instead, it should set the `INTERFACE` flag only if the class component of the intersection is `Object` (as the JLS says).
Once we do this, I'm confident that the existing checks in `Types` will rule out the bad intersection in this issue: because now it would be a class, not an interface -- so the existing check will kick in, and declare it not a suitable functional interface.
What do you think?
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/24548#discussion_r2039066742
More information about the compiler-dev
mailing list