diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java index e0d62e5d7f0..84f7f98af28 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -4681,10 +4681,10 @@ protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, receiverType = receiverType instanceof CaptureBinding ? receiverType : (ReferenceBinding) receiverType.erasure(); // within the boundaries of "chosen arbitrarily among the subset of the maximally specific methods that are preferred" - // put concrete methods first, default methods second: + // put implemented methods first: Arrays.sort(moreSpecific, (m1, m2) -> { - int rank1 = m1 == null ? 3 : m1.isAbstract() ? 2 : m1.isDefaultMethod() ? 1 : 0; - int rank2 = m2 == null ? 3 : m2.isAbstract() ? 2 : m2.isDefaultMethod() ? 1 : 0; + int rank1 = m1 == null ? 3 : m1.isAbstract() ? 2 : 0; + int rank2 = m2 == null ? 3 : m2.isAbstract() ? 2 : 0; return rank1 - rank2; }); boolean hasConsideredNullContract = false; @@ -4703,7 +4703,7 @@ protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, if (TypeBinding.equalsEquals(original.declaringClass, original2.declaringClass)) break nextSpecific; // duplicates thru substitution - if (!original.isAbstract()) { + if (!original.isAbstract() && !original.isDefaultMethod()) { if (original2.isAbstract() || original2.isDefaultMethod()) continue; // only compare current against other concrete methods diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java index 5f3c88f328e..5aca77198a1 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java @@ -3312,4 +3312,39 @@ default void setReadOnly(boolean readOnly) { } """}); } + public void testGH1600_2() { + runConformTest(new String[] {"Test.java", + """ + interface I0 { + default void m() throws Exception {} + default Number n() throws Exception { return 0l; } + } + interface I2 extends I0 { + @Override abstract void m() throws Exception; + @Override abstract Integer n() throws Exception; + } + class C2 implements I2 { + @Override public Integer n() throws Exception { return 13; } + @Override public void m() {} + } + public class Test { + void test1(I0 i) throws Exception { + if (i instanceof I2) + ((I2) i).m(); + else + System.out.print("no"); + } + void test2(I0 i0) throws Exception { + Integer i = ((I2) i0).n(); + System.out.print(i); + } + public static void main(String... args) throws Exception { + Test t = new Test(); + t.test1(new I0() {}); + t.test2(new C2()); + } + } + """}, + "no13"); + } }