Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorssankaran2014-08-26 06:15:38 +0000
committerssankaran2014-08-26 06:17:02 +0000
commit1412d255f0ba497d3ea8f98ac07c17128ae17670 (patch)
treed95e6ee5496d8e8a2cc6a217f3e5904c152e39c3
parentca5419c1e7501f8671202d3f26a44fb9de145612 (diff)
downloadeclipse.jdt.core-1412d255f0ba497d3ea8f98ac07c17128ae17670.tar.gz
eclipse.jdt.core-1412d255f0ba497d3ea8f98ac07c17128ae17670.tar.xz
eclipse.jdt.core-1412d255f0ba497d3ea8f98ac07c17128ae17670.zip
Fixed Bug 436350 - [1.8][compiler] Missing bridge method in interface
results in AbstractMethodError
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java117
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java2
2 files changed, 118 insertions, 1 deletions
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 68cfa6f6a1..7e881b022f 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
@@ -11,9 +11,13 @@
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
+import java.io.File;
import java.util.Map;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import junit.framework.Test;
@@ -2524,4 +2528,117 @@ public class InterfaceMethodsTest extends AbstractComparableTest {
},
"");
}
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=436350, [1.8][compiler] Missing bridge method in interface results in AbstractMethodError
+ public void test436350() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " }\n" +
+ "}\n" +
+ "interface GenericInterface<T> {\n" +
+ " T reduce(Integer i);\n" +
+ "}\n" +
+ "interface DoubleInterface extends GenericInterface<Double> {\n" +
+ " default Double reduce(Integer i) {\n" +
+ " return 0.0;\n" +
+ " }\n" +
+ " double reduce(String s);\n" +
+ "}\n", // =================
+ },
+ "");
+ // ensure bridge methods are generated in interfaces.
+ String expectedOutput =
+ " public bridge synthetic java.lang.Object reduce(java.lang.Integer arg0);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 aload_1 [arg0]\n" +
+ " 2 invokeinterface DoubleInterface.reduce(java.lang.Integer) : java.lang.Double [24] [nargs: 2]\n" +
+ " 7 areturn\n";
+
+ File f = new File(OUTPUT_DIR + File.separator + "DoubleInterface.class");
+ byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
+ ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
+ String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
+ int index = result.indexOf(expectedOutput);
+ if (index == -1 || expectedOutput.length() == 0) {
+ System.out.println(Util.displayString(result, 3));
+ }
+ if (index == -1) {
+ assertEquals("Wrong contents", expectedOutput, result);
+ }
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=436350, [1.8][compiler] Missing bridge method in interface results in AbstractMethodError
+ public void test436350a() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.Iterator;\n" +
+ "import java.util.PrimitiveIterator;\n" +
+ "import java.util.PrimitiveIterator.OfDouble;\n" +
+ "/**\n" +
+ " * @author Tobias Grasl\n" +
+ " */\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " final double[] doubles = new double[]{1,2,3};\n" +
+ " OfDouble doubleIterator = new DoubleArrayIterator(doubles);\n" +
+ " Double value = new Reducer<Double>().reduce(doubleIterator, new DoubleInterface() {\n" +
+ " @Override\n" +
+ " public double reduce(OfDouble iterator_) {\n" +
+ " double sum = 0;\n" +
+ " while(iterator_.hasNext()) {\n" +
+ " sum += iterator_.nextDouble();\n" +
+ " }\n" +
+ " return sum;\n" +
+ " }\n" +
+ " });\n" +
+ " System.out.println(\"Anonymous class value: \"+value);\n" +
+ " doubleIterator = new DoubleArrayIterator(doubles);\n" +
+ " value = new Reducer<Double>().reduce(doubleIterator, (DoubleInterface) iterator_ -> {\n" +
+ " double sum = 0;\n" +
+ " while(iterator_.hasNext()) {\n" +
+ " sum += iterator_.nextDouble();\n" +
+ " }\n" +
+ " return sum;\n" +
+ " });\n" +
+ " System.out.println(\"Lambda expression value: \"+value);\n" +
+ " }\n" +
+ " private static class DoubleArrayIterator implements PrimitiveIterator.OfDouble {\n" +
+ " int index = 0;\n" +
+ " private double[] _doubles;\n" +
+ " public DoubleArrayIterator(double[] doubles_) {\n" +
+ " _doubles = doubles_;\n" +
+ " }\n" +
+ " @Override\n" +
+ " public boolean hasNext() {\n" +
+ " return index < _doubles.length;\n" +
+ " }\n" +
+ " @Override\n" +
+ " public double nextDouble() {\n" +
+ " return _doubles[index++];\n" +
+ " }\n" +
+ " };\n" +
+ " interface GenericInterface<T> {\n" +
+ " T reduce(Iterator<T> iterator_);\n" +
+ " }\n" +
+ " interface DoubleInterface extends GenericInterface<Double> {\n" +
+ " default Double reduce(Iterator<Double> iterator_) {\n" +
+ " if(iterator_ instanceof PrimitiveIterator.OfDouble) {\n" +
+ " return reduce((PrimitiveIterator.OfDouble)iterator_);\n" +
+ " }\n" +
+ " return Double.NaN;\n" +
+ " };\n" +
+ " double reduce(PrimitiveIterator.OfDouble iterator_);\n" +
+ " }\n" +
+ " static class Reducer<T> {\n" +
+ " T reduce(Iterator<T> iterator_, GenericInterface<T> reduction_) {\n" +
+ " return reduction_.reduce(iterator_);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n", // =================
+ },
+ "Anonymous class value: 6.0\n" +
+ "Lambda expression value: 6.0");
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 9325e6221c..4dc56a837e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -692,7 +692,7 @@ public SyntheticMethodBinding addSyntheticFactoryMethod(MethodBinding privateCon
*/
public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding targetMethod) {
if (!isPrototype()) throw new IllegalStateException();
- if (isInterface()) return null; // only classes & enums get bridge methods
+ if (isInterface() && this.scope.compilerOptions().sourceLevel <= ClassFileConstants.JDK1_7) return null; // only classes & enums get bridge methods, interfaces too at 1.8+
// targetMethod may be inherited
if (TypeBinding.equalsEquals(inheritedMethodToBridge.returnType.erasure(), targetMethod.returnType.erasure())
&& inheritedMethodToBridge.areParameterErasuresEqual(targetMethod)) {

Back to the top