diff options
author | Andrey Loskutov | 2019-12-06 22:59:59 +0000 |
---|---|---|
committer | Stephan Herrmann | 2019-12-15 21:38:10 +0000 |
commit | bea783c841d5c85a86f047b715181e363e74ba62 (patch) | |
tree | a15b7af344d54a8d1887786a5e9f8a65d0be4b53 | |
parent | b232dab5f7ce89322dae86fcd5334d03116ec929 (diff) | |
download | eclipse.jdt.core-bea783c841d5c85a86f047b715181e363e74ba62.tar.gz eclipse.jdt.core-bea783c841d5c85a86f047b715181e363e74ba62.tar.xz eclipse.jdt.core-bea783c841d5c85a86f047b715181e363e74ba62.zip |
Bug 553885 - BootstrapMethodError for method reference to inheritedI20191215-1800
non-public default method
See https://bugs.openjdk.java.net/browse/JDK-8068253 as root cause and
https://bugs.openjdk.java.net/browse/JDK-8068254 as workaround in javac.
Reference expressions to default methods from package protected
interfaces should use implicit lambda methods to avoid runtime errors.
Change-Id: Iec5121bd4d8814a4348519dd25efc454deb61908
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
Also-by: Stephan Herrmann <stephan.herrmann@berlin.de>
2 files changed, 106 insertions, 1 deletions
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 5be3c39bc7..b11075770d 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 @@ -6846,6 +6846,109 @@ public void testBug529199() { "A.m" ); } +public void testBug553885a() { + runConformTest( + new String[] { + "p2/Test.java", + "package p2;\n" + + "import java.util.Optional;\n" + + "import p1.B;\n" + + "import p1.BImpl;\n" + + "\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " Optional<Integer> map = Optional.of(new BImpl()).map(B::amount);\n" + + " System.out.print(map);\n" + + " }\n" + + "}", + "p1/A.java", + "package p1;\n" + + "interface A {\n" + + " default int amount() {\n" + + " return 0;\n" + + " }\n" + + "}\n", + "p1/B.java", + "package p1;\n" + + "public interface B extends A {}\n" + + "\n", + "p1/BImpl.java", + "package p1;\n" + + "public class BImpl implements B {}\n", + }, + "Optional[0]" + ); +} +public void testBug553885b() { + runConformTest( + new String[] { + "p2/Test.java", + "package p2;\n" + + "import java.util.Optional;\n" + + "import p1.B;\n" + + "import p1.BImpl;\n" + + "\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " B b = new BImpl();\n" + // lead inference towards Optional<B> instead of Optional<BImpl> + " Optional<Integer> map = Optional.of(b).map(B::amount);\n" + + " System.out.print(map);\n" + + " }\n" + + "}", + "p1/A.java", + "package p1;\n" + + "interface A {\n" + + " default int amount() {\n" + + " return 0;\n" + + " }\n" + + "}\n", + "p1/B.java", + "package p1;\n" + + "public interface B extends A {}\n" + + "\n", + "p1/BImpl.java", + "package p1;\n" + + "public class BImpl implements B {}\n", + }, + "Optional[0]" + ); +} +public void testBug553885c() { + // classes instead of interface with default method + runConformTest( + new String[] { + "p2/Test.java", + "package p2;\n" + + "import java.util.Optional;\n" + + "import p1.B;\n" + + "import p1.BImpl;\n" + + "\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " B b = new BImpl();\n" + + " Optional<Integer> map = Optional.of(b).map(B::amount);\n" + + " System.out.print(map);\n" + + " }\n" + + "}", + "p1/A.java", + "package p1;\n" + + "class A {\n" + + " public int amount() {\n" + + " return 0;\n" + + " }\n" + + "}\n", + "p1/B.java", + "package p1;\n" + + "public class B extends A {}\n" + + "\n", + "p1/BImpl.java", + "package p1;\n" + + "public class BImpl extends B {}\n", + }, + "Optional[0]" + ); +} + public void testBug521182() { runConformTest( new String[] { 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 cfa39258eb..dc687c59df 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 @@ -287,9 +287,11 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx if (TypeBinding.notEquals(this.binding.declaringClass, this.lhs.resolvedType.erasure())) { // reference to a method declared by an inaccessible type accessed via a // subtype - normally a bridge method would be present to facilitate - // this access, unless the method is final/static, in which case, direct access to + // this access, unless the method is final/static/default, in which case, direct access to // the method is not possible, an implicit lambda is needed if (!this.binding.declaringClass.canBeSeenBy(this.enclosingScope)) { + if (this.binding.isDefaultMethod()) + return false; // workaround for bug in MethodHandle lookup, see https://bugs.openjdk.java.net/browse/JDK-8068253 return !(this.binding.isFinal() || this.binding.isStatic()); } } |