Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8059632

Method reference compilation uses incorrect qualifying type

    XMLWordPrintable

    Details

      Description

      public class InterfaceMethodref {

        interface I { void m(); }
        abstract class C implements I {}

        public void test(C arg) {
          Runnable r = arg::m;
        }

      }

      The method reference 'arg::m' compiles to:

               6: invokedynamic #3, 0 // InvokeDynamic #0:run:(LInterfaceMethodref$C;)Ljava/lang/Runnable;

      With bootstrap method:

        0: #22 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
          Method arguments:
            #23 ()V
            #24 invokeinterface InterfaceMethodref$I.m:()V
            #23 ()V

      Note that the metafactory call's implMethod is "invokeinterface InterfaceMethodref$I.m:()V", not "invokevirtual InterfaceMethodref$C.m:()V". This is incorrect: the compiler must refer to the type of the receiver, not the type of the declaring class/interface, per JLS 13.1 (see "the qualifying type of the method invocation").

      Also, FWIW, this combination of implMethod and invokedType violates the invariants claimed to be enforced by LambdaMetafactory (specifically, referring to the Javadoc, D1 != A1). Apparently this isn't currently enforced.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              dlsmith Dan Smith
              Reporter:
              dlsmith Dan Smith
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated: