Fixed bug 500374 Using a method reference to a generic method in a Base
class gives me NoSuchMethodError

Change-Id: Ide51e5877412a863a570314fc0ef881191fe1965
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
index 2e006c2..74b2de1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
@@ -6208,6 +6208,85 @@
 		}
 	);
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=500374 Using a method reference to a generic method in a Base class gives me NoSuchMethodError
+public void test500374() {
+	this.runConformTest(
+		new String[] {
+			"client/Client.java",
+			"package client;\n" + 
+			"import lib.Sub;\n" + 
+			"public class Client {\n" + 
+			"    public static void main(String[] args) throws Throwable {\n" + 
+			"        Sub s1 = new Sub();\n" + 
+			"        doSomething(() -> s1.m());\n" + 
+			"        doSomething(s1::m);\n" + 
+			"    }\n" + 
+			"    interface Aaa {\n" + 
+			"        Object f() throws Throwable;\n" + 
+			"    }\n" + 
+			"    public static void doSomething(Aaa a) throws Throwable {\n" + 
+			"        System.out.println(\"Done\");\n" + 
+			"    }\n" + 
+			"}\n",
+			"lib/Sub.java",
+			"package lib;\n" + 
+			"public class Sub extends Base<Sub> {}",
+			"lib/Base.java",
+			"package lib;\n" + 
+			"class Base<T> {\n" + 
+			"    public T m() {\n" + 
+			"        System.out.println(\"m\");\n" + 
+			"        return thisInstance();\n" + 
+			"    }\n" + 
+			"    @SuppressWarnings(\"unchecked\")\n" + 
+			"    T thisInstance() {\n" + 
+			"        return (T) this;\n" + 
+			"    }\n" + 
+			"}"
+	},
+	"Done\n" +
+	"Done");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=500374 Using a method reference to a generic method in a Base class gives me NoSuchMethodError
+public void test500374a() {
+	this.runConformTest(
+		new String[] {
+			"client/Client.java",
+			"package client;\n" + 
+			"import java.lang.invoke.MethodHandle;\n" + 
+			"import java.lang.invoke.MethodHandles;\n" + 
+			"import java.lang.invoke.MethodType;\n" + 
+			"import lib.Sub;\n" + 
+			"public class Client {\n" + 
+			"    public static void main(String[] args) throws Throwable {\n" + 
+			"        MethodHandle mh = MethodHandles.lookup().findVirtual(Sub.class, \"m\", MethodType.methodType(Object.class));\n" + 
+			"        doSomething(mh::invoke);\n" + 
+			"    }\n" + 
+			"    interface Aaa {\n" + 
+			"        Object f() throws Throwable;\n" + 
+			"    }\n" + 
+			"    public static void doSomething(Aaa a) throws Throwable {\n" + 
+			"        System.out.println(\"Done\");\n" + 
+			"    }\n" + 
+			"}\n",
+			"lib/Sub.java",
+			"package lib;\n" + 
+			"public class Sub extends Base<Sub> {}",
+			"lib/Base.java",
+			"package lib;\n" + 
+			"class Base<T> {\n" + 
+			"    public T m() {\n" + 
+			"        System.out.println(\"m\");\n" + 
+			"        return thisInstance();\n" + 
+			"    }\n" + 
+			"    @SuppressWarnings(\"unchecked\")\n" + 
+			"    T thisInstance() {\n" + 
+			"        return (T) this;\n" + 
+			"    }\n" + 
+			"}"
+	},
+	"Done");
+}
 public static Class testClass() {
 	return LambdaExpressionsTest.class;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index b500444..0aecb34 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -90,6 +90,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
@@ -3051,7 +3052,7 @@
 				this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex;
 	
-				int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below.
+				int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding instanceof PolymorphicMethodBinding ? functional.binding : functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below.
 				this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) methodHandleIndex;
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index 01adeb6..1b5c028 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -288,7 +288,7 @@
 			if (this.binding != null && isMethodReference()) {
 				if (TypeBinding.notEquals(this.binding.declaringClass, this.lhs.resolvedType.erasure())) {
 					if (!this.binding.declaringClass.canBeSeenBy(currentScope)) {
-						this.binding = new MethodBinding(this.binding, (ReferenceBinding) this.lhs.resolvedType.erasure());
+						this.binding = new MethodBinding(this.binding.original(), (ReferenceBinding) this.lhs.resolvedType.erasure());
 					}
 				}
 			}