Intersection type and method ref bug ?

B. Blaser bsrbnd at gmail.com
Thu Oct 15 14:56:18 UTC 2020


Hi,

Resurrecting this old thread as the following expression:

    Stream.of(new A(), new B()).map(Test::f).forEach(System.out::println);

still throws a LCE at runtime: "Type mismatch for lambda argument 0:
class Test$C is not convertible to interface Test$I".

>From 'Stream::of' we have 'Stream<C & I>' and then:

    <R> Stream<R> map(Function<? super C & I, ? extends R> mapper);

Further, wildcards are removed per JLS15 §9.9 resulting to the
functional descriptor 'apply(C & I)' finally erased to 'apply(C)'
which isn't convertible to 'lambda$main$0(Test$I)' that javac
currently generates, failing to detect the intersection type 'C & I'.

The following patch adds the missing lines to 'LambdaToMethod' on
jdk14u (langtools:tier1 is OK).

What do you think?
Bernard

diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
@@ -968,6 +968,10 @@
                 // If the unerased parameter type is a type variable whose
                 // bound is an intersection (eg. <T extends A & B>) then
                 // use the SAM parameter type
+                if (checkForIntersection && descPTypes.head.getKind()
== TypeKind.INTERSECTION) {
+                    parmType = samPTypes.head;
+                }
+
                 if (checkForIntersection && descPTypes.head.getKind()
== TypeKind.TYPEVAR) {
                     TypeVar tv = (TypeVar) descPTypes.head;
                     if (tv.getUpperBound().getKind() ==
TypeKind.INTERSECTION) {


On Fri, 26 Oct 2018 at 15:21, Vicente Romero <vicente.romero at oracle.com> wrote:
>
> Hi Remi, Francois,
>
> Thanks for reporting this. I have created [1] to track this issue,
>
> Vicente
>
> [1] https://bugs.openjdk.java.net/browse/JDK-8213032
>
> On 10/24/18 6:05 AM, Remi Forax wrote:
> > This bug was discovered by Francois Green when testing records, but the bug is independent of the record,
> > method reference and intersection type doesn't mix well.
> >
> > public class RecordBadType {
> >    interface  I {}
> >    static abstract class C { }
> >    static class A extends C implements I { }
> >    static class B extends C implements I { }
> >
> >    static String f(I i) { return null; }
> >
> >    public static void main(String[] args) {
> >      Stream.of(new A(), new B())
> >        .map(RecordBadType::f)   // here the compiler should generate a bridge method no ?
> >        .forEach(System.out::println);
> >    }
> > }
> >
> > this code compiles but you get a LambdaConversionException at runtime.
> >
> > Rémi
>


More information about the compiler-dev mailing list