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

Method reference compilation uses incorrect qualifying type

    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: