Intersection type and method ref bug ?

Vicente Romero vicente.romero at oracle.com
Tue Oct 20 20:06:15 UTC 2020


Hi Bernard,

The patch looks good to me. Do you need help with the git PR?

Vicente

On 10/15/20 10:56 AM, B. Blaser wrote:
> 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