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

Method reference compilation uses incorrect qualifying type

XMLWordPrintable

    • b25

      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.

            sadayapalam Srikanth Adayapalam (Inactive)
            dlsmith Dan Smith
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: