Fix a bug in method reference in Java8.
When using method references to methods that have the
same signature but from different classes, wrong method was called.
For example, f(A::id); f(B::id); A and B both have method id()
with the same signature, B::id() is not called correctly.
The reason is that the generated names of inner lambda class were
the same since they have the same method signature, thus only one
lambda class was created for A::id and B::id.
Fix the issue by adding class name to the generated inner class
name to identify different methods.
Bug: issue 9040
Change-Id: Ibc6b12d26d473ab32b821bb2202e78ae92670774
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 5d2f8d4..3e7e751 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -515,7 +515,7 @@
}
// My seed function name
- JsName jsName = topScope.declareName(getNameString(x), x.getShortName());
+ JsName jsName = topScope.declareName(JjsUtils.getNameString(x), x.getShortName());
names.put(x, jsName);
recordSymbol(x, jsName);
@@ -3405,11 +3405,6 @@
}
}
- static String getNameString(HasName hasName) {
- String s = hasName.getName().replaceAll("_", "_1").replace('.', '_');
- return s;
- }
-
/**
* Retrieves the runtime typeId for {@code type}.
*/
@@ -3425,12 +3420,13 @@
}
String mangleName(JField x) {
- String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x);
+ String s = JjsUtils.getNameString(x.getEnclosingType()) + '_' + JjsUtils.getNameString(x);
return s;
}
String mangleNameForGlobal(JMethod x) {
- String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x) + "__";
+ String s =
+ JjsUtils.getNameString(x.getEnclosingType()) + '_' + JjsUtils.getNameString(x) + "__";
for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
JType type = x.getOriginalParamTypes().get(i);
s += type.getJavahSignatureName();
@@ -3449,38 +3445,18 @@
*/
sb.append("package_private$");
JMethod topDefinition = typeOracle.getTopMostDefinition(x);
- sb.append(getNameString(topDefinition.getEnclosingType()));
+ sb.append(JjsUtils.getNameString(topDefinition.getEnclosingType()));
sb.append("$");
- sb.append(getNameString(x));
- constructManglingSignature(x, sb);
- return StringInterner.get().intern(sb.toString());
- }
-
- /**
- * Java8 Method References such as String::equalsIgnoreCase should produce inner class names
- * that are a function of the samInterface (e.g. Runnable), the method being referred to,
- * and the qualifying disposition (this::foo vs Class::foo if foo is an instance method)
- */
- static String classNameForMethodReference(JInterfaceType samInterface, JMethod referredMethod,
- boolean haveReceiver) {
- StringBuilder sb = new StringBuilder();
- sb.append(samInterface.getPackageName());
- sb.append('.');
- sb.append(samInterface.getShortName());
- sb.append("$");
- if (!haveReceiver) {
- sb.append("$");
- }
- sb.append(getNameString(referredMethod));
- constructManglingSignature(referredMethod, sb);
+ sb.append(JjsUtils.getNameString(x));
+ JjsUtils.constructManglingSignature(x, sb);
return StringInterner.get().intern(sb.toString());
}
String mangleNameForPoly(JMethod x) {
assert !x.isPrivate() && !x.isStatic();
StringBuilder sb = new StringBuilder();
- sb.append(getNameString(x));
- constructManglingSignature(x, sb);
+ sb.append(JjsUtils.getNameString(x));
+ JjsUtils.constructManglingSignature(x, sb);
return StringInterner.get().intern(sb.toString());
}
@@ -3493,10 +3469,10 @@
* class name to the mangled name.
*/
sb.append("private$");
- sb.append(getNameString(x.getEnclosingType()));
+ sb.append(JjsUtils.getNameString(x.getEnclosingType()));
sb.append("$");
- sb.append(getNameString(x));
- constructManglingSignature(x, sb);
+ sb.append(JjsUtils.getNameString(x));
+ JjsUtils.constructManglingSignature(x, sb);
return StringInterner.get().intern(sb.toString());
}
@@ -3504,20 +3480,11 @@
assert x.isJsProperty();
StringBuilder sb = new StringBuilder();
sb.append("jsproperty$");
- sb.append(getNameString(x));
- constructManglingSignature(x, sb);
+ sb.append(JjsUtils.getNameString(x));
+ JjsUtils.constructManglingSignature(x, sb);
return StringInterner.get().intern(sb.toString());
}
- private static void constructManglingSignature(JMethod x, StringBuilder partialSignature) {
- partialSignature.append("__");
- for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
- JType type = x.getOriginalParamTypes().get(i);
- partialSignature.append(type.getJavahSignatureName());
- }
- partialSignature.append(x.getOriginalReturnType().getJavahSignatureName());
- }
-
String mangleNameSpecialObfuscate(JField x) {
assert (specialObfuscatedFields.containsKey(x));
switch (output) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index ca13e5e..33f4a57 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -1745,7 +1745,7 @@
}
// Constructors and overloading mean we need generate unique names
- String lambdaName = GenerateJavaScriptAST.classNameForMethodReference(funcType,
+ String lambdaName = classNameForMethodReference(funcType,
referredMethod,
haveReceiver);
@@ -1922,6 +1922,28 @@
push(allocLambda);
}
+ /**
+ * Java8 Method References such as String::equalsIgnoreCase should produce inner class names
+ * that are a function of the samInterface (e.g. Runnable), the method being referred to,
+ * and the qualifying disposition (this::foo vs Class::foo if foo is an instance method)
+ */
+ private String classNameForMethodReference(JInterfaceType samInterface, JMethod referredMethod,
+ boolean haveReceiver) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(samInterface.getPackageName());
+ sb.append('.');
+ sb.append(samInterface.getShortName());
+ sb.append("$");
+ if (!haveReceiver) {
+ sb.append("$");
+ }
+ sb.append(referredMethod.getEnclosingType().getName().replace('.', '$'));
+ sb.append("$");
+ sb.append(JjsUtils.getNameString(referredMethod));
+ JjsUtils.constructManglingSignature(referredMethod, sb);
+ return StringInterner.get().intern(sb.toString());
+ }
+
private JExpression boxOrUnboxExpression(JExpression expr, TypeBinding fromType,
TypeBinding toType) {
if (fromType == TypeBinding.VOID || toType == TypeBinding.VOID) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
index 5bdfbdc..812115c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
@@ -18,6 +18,7 @@
import com.google.gwt.dev.PrecompileTaskOptions;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
+import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
import com.google.gwt.dev.jjs.ast.JCharLiteral;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
@@ -37,6 +38,7 @@
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JThisRef;
+import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsExpression;
@@ -174,6 +176,20 @@
delegate.addOverriddenMethod(methodToDelegate);
}
+ public static void constructManglingSignature(JMethod x, StringBuilder partialSignature) {
+ partialSignature.append("__");
+ for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
+ JType type = x.getOriginalParamTypes().get(i);
+ partialSignature.append(type.getJavahSignatureName());
+ }
+ partialSignature.append(x.getOriginalReturnType().getJavahSignatureName());
+ }
+
+ public static String getNameString(HasName hasName) {
+ String s = hasName.getName().replaceAll("_", "_1").replace('.', '_');
+ return s;
+ }
+
private enum LiteralTranslators {
BOOLEAN_LITERAL_TRANSLATOR() {
@Override
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/Java8AstTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/Java8AstTest.java
index 695c224..e99a81c 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/Java8AstTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/Java8AstTest.java
@@ -501,7 +501,7 @@
addSnippetClassDecl("public static Integer foo(int x, int y) { return x + y; }");
String lambda = "new AcceptsLambda<Integer>().accept(EntryPoint::foo);";
assertEqualBlock(
- "(new AcceptsLambda()).accept(new Lambda$$foo__IILjava_lang_Integer_2$Type());",
+ "(new AcceptsLambda()).accept(new Lambda$$test$EntryPoint$foo__IILjava_lang_Integer_2$Type());",
lambda
);
JProgram program = compileSnippet("void", lambda, false);
@@ -510,11 +510,11 @@
// created by GwtAstBuilder
JClassType lambdaInnerClass = (JClassType) getType(program,
- "test.Lambda$$foo__IILjava_lang_Integer_2$Type");
+ "test.Lambda$$test$EntryPoint$foo__IILjava_lang_Integer_2$Type");
assertNotNull(lambdaInnerClass);
// should have constructor taking this and x
- JMethod ctor = findMethod(lambdaInnerClass, "Lambda$$foo__IILjava_lang_Integer_2$Type");
+ JMethod ctor = findMethod(lambdaInnerClass, "Lambda$$test$EntryPoint$foo__IILjava_lang_Integer_2$Type");
assertTrue(ctor instanceof JConstructor);
// no ctor args
assertEquals(0, ctor.getParams().size());
@@ -536,7 +536,7 @@
addSnippetClassDecl("public Integer foo(int x, int y) { return x + y; }");
String lambda = "new AcceptsLambda<Integer>().accept(this::foo);";
assertEqualBlock(
- "(new AcceptsLambda()).accept(new Lambda$foo__IILjava_lang_Integer_2$Type(this));",
+ "(new AcceptsLambda()).accept(new Lambda$test$EntryPoint$foo__IILjava_lang_Integer_2$Type(this));",
lambda
);
JProgram program = compileSnippet("void", lambda, false);
@@ -545,11 +545,11 @@
// created by GwtAstBuilder
JClassType lambdaInnerClass = (JClassType) getType(program,
- "test.Lambda$foo__IILjava_lang_Integer_2$Type");
+ "test.Lambda$test$EntryPoint$foo__IILjava_lang_Integer_2$Type");
assertNotNull(lambdaInnerClass);
// should have constructor taking this and x
- JMethod ctor = findMethod(lambdaInnerClass, "Lambda$foo__IILjava_lang_Integer_2$Type");
+ JMethod ctor = findMethod(lambdaInnerClass, "Lambda$test$EntryPoint$foo__IILjava_lang_Integer_2$Type");
assertTrue(ctor instanceof JConstructor);
// instance capture
assertEquals(1, ctor.getParams().size());
@@ -577,19 +577,21 @@
"new AcceptsLambda<Integer>().accept(instance1::fooInstance);\n" +
"new AcceptsLambda<Integer>().accept(instance2::fooInstance);";
assertEqualBlock(
- "(new AcceptsLambda()).accept(new Lambda$fooInstance__IILjava_lang_Integer_2$Type(this.instance1));\n"
- + "(new AcceptsLambda()).accept(new Lambda$fooInstance__IILjava_lang_Integer_2$Type(this.instance2));",
+ "(new AcceptsLambda()).accept(new "
+ + "Lambda$test$Pojo$fooInstance__IILjava_lang_Integer_2$Type(this.instance1));\n"
+ + "(new AcceptsLambda()).accept(new "
+ + "Lambda$test$Pojo$fooInstance__IILjava_lang_Integer_2$Type(this.instance2));",
reference);
JProgram program = compileSnippet("void", reference, false);
// created by GwtAstBuilder
JClassType lambdaInnerClass = (JClassType) getType(program,
- "test.Lambda$fooInstance__IILjava_lang_Integer_2$Type");
+ "test.Lambda$test$Pojo$fooInstance__IILjava_lang_Integer_2$Type");
assertNotNull(lambdaInnerClass);
assertEquals(1, Collections.frequency(program.getDeclaredTypes(), lambdaInnerClass));
// should have constructor taking the instance
- JMethod ctor = findMethod(lambdaInnerClass, "Lambda$fooInstance__IILjava_lang_Integer_2$Type");
+ JMethod ctor = findMethod(lambdaInnerClass, "Lambda$test$Pojo$fooInstance__IILjava_lang_Integer_2$Type");
assertTrue(ctor instanceof JConstructor);
// instance capture
assertEquals(1, ctor.getParams().size());
@@ -610,23 +612,152 @@
formatSource(samMethod.toSource()));
}
+ public void testCompileInstanceReferenceBindingMultipleWithSameMethodSignature() throws Exception {
+ addSnippetClassDecl("static class TestMF_A {\n" +
+ " public String getId() {\n" +
+ " return \"A\";\n" +
+ " }\n" +
+ " }");
+ addSnippetClassDecl(" static class TestMF_B {\n" +
+ " public String getId() {\n" +
+ " return \"B\";\n" +
+ " }\n" +
+ " }");
+ addSnippetClassDecl("interface Function<T> {\n" +
+ " T apply();\n" +
+ " }");
+ addSnippetClassDecl(" private String f(Function<String> arg) {\n" +
+ " return arg.apply();\n" +
+ " }");
+ String reference = "TestMF_A a = new TestMF_A();\n"
+ + "TestMF_B b = new TestMF_B();\n"
+ + "f(a::getId);\n"
+ + "f(b::getId);";
+ assertEqualBlock(
+ "EntryPoint$TestMF_A a=new EntryPoint$TestMF_A();"
+ + "EntryPoint$TestMF_B b=new EntryPoint$TestMF_B();"
+ + "this.f(new "
+ + "EntryPoint$Function$test$EntryPoint$TestMF_A$getId__Ljava_lang_String_2$Type(a));"
+ + "this.f(new "
+ + "EntryPoint$Function$test$EntryPoint$TestMF_B$getId__Ljava_lang_String_2$Type(b));",
+ reference);
+ JProgram program = compileSnippet("void", reference, false);
+
+ // created by GwtAstBuilder
+ JClassType innerClassA = (JClassType) getType(program,
+ "test.EntryPoint$Function$test$EntryPoint$TestMF_A$getId__Ljava_lang_String_2$Type");
+ JClassType innerClassB = (JClassType) getType(program,
+ "test.EntryPoint$Function$test$EntryPoint$TestMF_B$getId__Ljava_lang_String_2$Type");
+ assertNotNull(innerClassA);
+ assertNotNull(innerClassB);
+
+ // should have constructor taking this and x
+ JMethod ctorA = findMethod(innerClassA,
+ "EntryPoint$Function$test$EntryPoint$TestMF_A$getId__Ljava_lang_String_2$Type");
+ assertTrue(ctorA instanceof JConstructor);
+ // instance capture
+ assertEquals(1, ctorA.getParams().size());
+ assertEquals("test.EntryPoint$TestMF_A", ctorA.getOriginalParamTypes().get(0).getName());
+ JMethod ctorB = findMethod(innerClassB,
+ "EntryPoint$Function$test$EntryPoint$TestMF_B$getId__Ljava_lang_String_2$Type");
+ assertTrue(ctorB instanceof JConstructor);
+ // instance capture
+ assertEquals(1, ctorB.getParams().size());
+ assertEquals("test.EntryPoint$TestMF_B", ctorB.getOriginalParamTypes().get(0).getName());
+
+ // should have 1 field to store the captured instance
+ assertEquals(1, innerClassA.getFields().size());
+ assertEquals("test.EntryPoint$TestMF_A",
+ innerClassA.getFields().get(0).getType().getName());
+ assertEquals(1, innerClassB.getFields().size());
+ assertEquals("test.EntryPoint$TestMF_B",
+ innerClassB.getFields().get(0).getType().getName());
+
+ // should extends EntryPoint$Function
+ assertTrue(
+ innerClassA.getImplements().contains(program.getFromTypeMap("test.EntryPoint$Function")));
+ assertTrue(
+ innerClassB.getImplements().contains(program.getFromTypeMap("test.EntryPoint$Function")));
+
+ // should implement apply method
+ JMethod samMethodA = findMethod(innerClassA, "apply");
+ assertEquals(
+ "public final Object apply(){return this.$$outer_0.getId();}",
+ formatSource(samMethodA.toSource()));
+ JMethod samMethodB = findMethod(innerClassB, "apply");
+ assertEquals(
+ "public final Object apply(){return this.$$outer_0.getId();}",
+ formatSource(samMethodB.toSource()));
+ }
+
+ public void testCompileStaticReferenceBindingMultiple() throws Exception {
+ addSnippetClassDecl("static class TestMF_A {\n" +
+ " public static String getId() {\n" +
+ " return \"A\";\n" +
+ " }\n" +
+ " }");
+ addSnippetClassDecl(" static class TestMF_B {\n" +
+ " public static String getId() {\n" +
+ " return \"B\";\n" +
+ " }\n" +
+ " }");
+ addSnippetClassDecl("interface Function<T> {\n" +
+ " T apply();\n" +
+ " }");
+ addSnippetClassDecl(" private String f(Function<String> arg) {\n" +
+ " return arg.apply();\n" +
+ " }");
+ String reference = "f(TestMF_A::getId);\n" + "f(TestMF_B::getId);";
+ assertEqualBlock(
+ "this.f(new "
+ + "EntryPoint$Function$$test$EntryPoint$TestMF_A$getId__Ljava_lang_String_2$Type());"
+ + "this.f(new "
+ + "EntryPoint$Function$$test$EntryPoint$TestMF_B$getId__Ljava_lang_String_2$Type());",
+ reference);
+ JProgram program = compileSnippet("void", reference, false);
+
+ // created by GwtAstBuilder
+ JClassType innerClassA = (JClassType) getType(program,
+ "test.EntryPoint$Function$$test$EntryPoint$TestMF_A$getId__Ljava_lang_String_2$Type");
+ JClassType innerClassB = (JClassType) getType(program,
+ "test.EntryPoint$Function$$test$EntryPoint$TestMF_B$getId__Ljava_lang_String_2$Type");
+ assertNotNull(innerClassA);
+ assertNotNull(innerClassB);
+
+ // should extends EntryPoint$Function
+ assertTrue(
+ innerClassA.getImplements().contains(program.getFromTypeMap("test.EntryPoint$Function")));
+ assertTrue(
+ innerClassB.getImplements().contains(program.getFromTypeMap("test.EntryPoint$Function")));
+
+ // should implement apply method
+ JMethod samMethodA = findMethod(innerClassA, "apply");
+ assertEquals(
+ "public final Object apply(){return EntryPoint$TestMF_A.getId();}",
+ formatSource(samMethodA.toSource()));
+ JMethod samMethodB = findMethod(innerClassB, "apply");
+ assertEquals(
+ "public final Object apply(){return EntryPoint$TestMF_B.getId();}",
+ formatSource(samMethodB.toSource()));
+ }
+
public void testCompileImplicitQualifierReferenceBinding() throws Exception {
String lambda = "new AcceptsLambda<String>().accept2(String::equalsIgnoreCase);";
assertEqualBlock(
"(new AcceptsLambda()).accept2("
- + "new Lambda2$$equalsIgnoreCase__Ljava_lang_String_2Z$Type());",
+ + "new Lambda2$$java$lang$String$equalsIgnoreCase__Ljava_lang_String_2Z$Type());",
lambda
);
JProgram program = compileSnippet("void", lambda, false);
// created by GwtAstBuilder
JClassType lambdaInnerClass = (JClassType) getType(program,
- "test.Lambda2$$equalsIgnoreCase__Ljava_lang_String_2Z$Type");
+ "test.Lambda2$$java$lang$String$equalsIgnoreCase__Ljava_lang_String_2Z$Type");
assertNotNull(lambdaInnerClass);
// should have constructor taking this and x
JMethod ctor = findMethod(lambdaInnerClass,
- "Lambda2$$equalsIgnoreCase__Ljava_lang_String_2Z$Type");
+ "Lambda2$$java$lang$String$equalsIgnoreCase__Ljava_lang_String_2Z$Type");
assertTrue(ctor instanceof JConstructor);
// no instance capture
assertEquals(0, ctor.getParams().size());
@@ -647,17 +778,18 @@
public void testCompileConstructorReferenceBinding() throws Exception {
String lambda = "new AcceptsLambda<Pojo>().accept(Pojo::new);";
assertEqualBlock(
- "(new AcceptsLambda()).accept(new Lambda$$Pojo__IIV$Type());",
+ "(new AcceptsLambda()).accept(new Lambda$$test$Pojo$Pojo__IIV$Type());",
lambda
);
JProgram program = compileSnippet("void", lambda, false);
// created by GwtAstBuilder
- JClassType lambdaInnerClass = (JClassType) getType(program, "test.Lambda$$Pojo__IIV$Type");
+ JClassType lambdaInnerClass = (JClassType) getType(program,
+ "test.Lambda$$test$Pojo$Pojo__IIV$Type");
assertNotNull(lambdaInnerClass);
// should have constructor taking this and x
- JMethod ctor = findMethod(lambdaInnerClass, "Lambda$$Pojo__IIV$Type");
+ JMethod ctor = findMethod(lambdaInnerClass, "Lambda$$test$Pojo$Pojo__IIV$Type");
assertTrue(ctor instanceof JConstructor);
// no instance capture
assertEquals(0, ctor.getParams().size());
@@ -691,19 +823,19 @@
String lambda = "new AcceptsLambda<Pojo2>().accept(Pojo2::new);";
assertEqualBlock(
"(new AcceptsLambda()).accept("
- + "new Lambda$$EntryPoint$Pojo2__Ltest_EntryPoint_2IIV$Type(this));",
+ + "new Lambda$$test$EntryPoint$Pojo2$EntryPoint$Pojo2__Ltest_EntryPoint_2IIV$Type(this));",
lambda
);
JProgram program = compileSnippet("void", lambda, false);
// created by GwtAstBuilder
JClassType lambdaInnerClass = (JClassType) getType(program,
- "test.Lambda$$EntryPoint$Pojo2__Ltest_EntryPoint_2IIV$Type");
+ "test.Lambda$$test$EntryPoint$Pojo2$EntryPoint$Pojo2__Ltest_EntryPoint_2IIV$Type");
assertNotNull(lambdaInnerClass);
// should have constructor taking this and x
JMethod ctor = findMethod(lambdaInnerClass,
- "Lambda$$EntryPoint$Pojo2__Ltest_EntryPoint_2IIV$Type");
+ "Lambda$$test$EntryPoint$Pojo2$EntryPoint$Pojo2__Ltest_EntryPoint_2IIV$Type");
assertTrue(ctor instanceof JConstructor);
// one instance capture
assertEquals(1, ctor.getParams().size());
diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java
index ad5ed5a..6e4d76e 100644
--- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java
+++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java
@@ -851,4 +851,39 @@
assertEquals(20, b.s[0]);
assertEquals(30, result);
}
+
+ static class TestMF_A {
+ public static String getId() {
+ return "A";
+ }
+ public int getIdx() {
+ return 1;
+ }
+ }
+ static class TestMF_B {
+ public static String getId() {
+ return "B";
+ }
+ public int getIdx() {
+ return 2;
+ }
+ }
+ interface Function<T> {
+ T apply();
+ }
+ private String f(Function<String> arg) {
+ return arg.apply();
+ }
+ private int g(Function<Integer> arg) {
+ return arg.apply().intValue();
+ }
+
+ public void testMethodRefWithSameName() {
+ assertEquals("A", f(TestMF_A::getId));
+ assertEquals("B", f(TestMF_B::getId));
+ TestMF_A a = new TestMF_A();
+ TestMF_B b = new TestMF_B();
+ assertEquals(1, g(a::getIdx));
+ assertEquals(2, g(b::getIdx));
+ }
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java
index 05dca4c..4094695 100644
--- a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java
+++ b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java
@@ -168,4 +168,7 @@
public void testLambdaMultipleNestingCaptureFieldAndLocalInnerClass() {
}
+
+ public void testMethodRefWithSameName() {
+ }
}
\ No newline at end of file