Revert "Fixed bug 467776 [compiler][implementation] decouple method verification from bridge method generation"

This reverts commit 65386f283034d2adbed1c5efa5bf0164d0891bf0.
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index f022ecc..a2458df 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -33089,7 +33089,7 @@
 			"1. ERROR in X.java (at line 7)\n" + 
 			"	abstract class GLinkElementView<M,CM> extends AbstractLinkView<M> {}\n" + 
 			"	               ^^^^^^^^^^^^^^^^\n" + 
-			"The return types are incompatible for the inherited methods EditPart.getViewer(), AbstractLinkView<M>.getViewer()\n" + 
+			"The return types are incompatible for the inherited methods ILinkViewElement.getViewer(), EditPart.getViewer(), AbstractLinkView<M>.getViewer()\n" + 
 			"----------\n" + 
 			"2. ERROR in X.java (at line 11)\n" + 
 			"	public SheetViewer getViewer() { return null; }	\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
index a4c90fe..edb77db 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
@@ -14207,68 +14207,4 @@
 		assertEquals("Wrong contents", expectedOutput, result);
 	}
 }
-// https://bugs.eclipse.org/bugs/show_bug.cgi?id=438812, Missing bridge methods in indirect child classes with ECJ 3.10.0
-public void testBug438812a() throws Exception {
-	this.runConformTest(
-		new String[] {
-			"A.java",
-			"import java.util.Collection;\n" + 
-			"import java.util.List;\n" + 
-			"\n" + 
-			"public abstract class A {\n" + 
-			"    abstract Iterable getIterable();\n" + 
-			"}\n" + 
-			"\n" + 
-			"class B extends A {\n" + 
-			"    public Collection getIterable() { return null; }\n" + 
-			"}\n" + 
-			"\n" + 
-			"class C extends B {\n" + 
-			"    public List getIterable() { return null; }\n" + 
-			"}",
-		},
-		"");
-	String expectedOutput = "  public bridge synthetic java.lang.Iterable getIterable();";
-
-	File f = new File(OUTPUT_DIR + File.separator + "C.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=461529, Abstract class extending interface with default impl won't compile, but does compile from cmd line
-public void testBug461529() throws Exception {
-	if (this.complianceLevel < ClassFileConstants.JDK1_8) return;
-	this.runConformTest(
-		new String[] {
-			"foo/IBarable.java",
-			"package foo;\n" + 
-			"public interface IBarable<T extends IBarable<T>> {\n" + 
-			"    default IBar<T> createBar() {\n" + 
-			"        throw new UnsupportedOperationException();\n" + 
-			"    }\n" + 
-			"}\n",
-			"foo/IBar.java",
-			"package foo;\n" + 
-			"public interface IBar<T extends IBarable<T>> {\n" + 
-			"    T bar();\n" + 
-			"}\n",
-			"foo/Foo.java",
-			"package foo;\n" + 
-			"public abstract class Foo implements IBarable<Foo> {\n" + 
-			"    public abstract static class Builder implements IBar<Foo> {}\n" + 
-			"    @Override\n" + 
-			"    public abstract Builder createBar();\n" + 
-			"}\n",
-			"foo/ChildFoo.java",
-			"package foo;\n" + 
-			"public abstract class ChildFoo extends Foo {}\n"
-		});
-}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
index 936e738..58166ae 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
@@ -40,11 +40,6 @@
 	SourceTypeBinding type;
 	HashtableOfObject inheritedMethods;
 	HashtableOfObject currentMethods;
-	/** 
-	 * Methods that are to be considered inherited even though they are overridden somewhere in the
-	 * hierarchy - notably for bridge method generation
-	 */
-	HashtableOfObject inheritedOverriddenMethods;
 	/*
 Binding creation is responsible for reporting all problems with types:
 	- all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - abstract/final)
@@ -67,7 +62,6 @@
 	this.type = null;  // Initialized with the public method verify(SourceTypeBinding)
 	this.inheritedMethods = null;
 	this.currentMethods = null;
-	this.inheritedOverriddenMethods = null;
 }
 boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
 	return areMethodsCompatible(one, two, this.environment);
@@ -197,25 +191,6 @@
 		if (!inheritedMethod.isStatic() && !inheritedMethod.isFinal())
 			checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods);
 	}
-	MethodBinding[] overridden = (MethodBinding[])this.inheritedOverriddenMethods.get(currentMethod.selector);
-	if (overridden != null) {
-		for (int i = overridden.length; --i >= 0;) {
-			MethodBinding inheritedMethod = overridden[i];
-			if (!inheritedMethod.isStatic() && !inheritedMethod.isFinal())
-				checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods);
-		}
-	}
-}
-void addBridgeMethodCandidate(MethodBinding overriddenMethod) {
-	MethodBinding[] existing = (MethodBinding[])this.inheritedOverriddenMethods.get(overriddenMethod.selector);
-	if (existing == null) {
-		existing = new MethodBinding[]{overriddenMethod};
-	} else {
-		int length = existing.length;
-		System.arraycopy(existing, 0, existing = new MethodBinding[length + 1], 0, length);
-		existing[length] = overriddenMethod;
-	}
-	this.inheritedOverriddenMethods.put(overriddenMethod.selector, existing);
 }
 
 public void reportRawReferences(MethodBinding currentMethod, MethodBinding inheritedMethod) {
@@ -529,7 +504,6 @@
     // see usage of canOverridingMethodDifferInErasure below.
 	this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
 
-	this.inheritedOverriddenMethods = new HashtableOfObject(11);
 	ReferenceBinding superType = superclass;
 	HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods
 
@@ -555,10 +529,6 @@
 									continue existing; // may need to record incompatible return type
 							}
 						}
-						if (TypeBinding.notEquals(inheritedMethod.returnType, existingMethod.returnType) &&
-								areReturnTypesCompatible(existingMethod, inheritedMethod)) {
-							addBridgeMethodCandidate(inheritedMethod);
-						}
 						continue nextMethod;
 					}
 				}
@@ -642,17 +612,9 @@
 					// look to see if any of the existingMethods implement this inheritedMethod
 					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302358, skip inherited method only if any overriding version
 					// in a subclass is guaranteed to have the same erasure as an existing method.
-					for (int e = 0; e < length; e++) {
-						if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType)) {
-							if (TypeBinding.notEquals(inheritedMethod.returnType, existingMethods[e].returnType)) {
-								// overridden, but with different return type, need to check
-								// for bridge method
-								addBridgeMethodCandidate(inheritedMethod);
-							}
-							if (!canOverridingMethodDifferInErasure(existingMethods[e], inheritedMethod))
-								continue nextMethod;
-						}
-					}
+					for (int e = 0; e < length; e++)
+						if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType) && !canOverridingMethodDifferInErasure(existingMethods[e], inheritedMethod))
+							continue nextMethod; // skip interface method with the same signature if visible to its declaringClass
 					System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
 					existingMethods[length] = inheritedMethod;
 				}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
index b583e89..2fa02c9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -949,18 +949,21 @@
 			return true;
 	}
 }
-// caveat: returns false if a method is implemented, but with a return type that is incompatible with that of the interface method
+// caveat: returns false if a method is implemented that needs a bridge method
 boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
 	if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface())
 		return false; // must hold onto ParameterizedMethod to see if a bridge method is necessary
 
 	inheritedMethod = computeSubstituteMethod(inheritedMethod, existingMethod);
-	if (inheritedMethod == null	|| !doesMethodOverride(existingMethod, inheritedMethod))
+	if (inheritedMethod == null
+			|| TypeBinding.notEquals(inheritedMethod.returnType, existingMethod.returnType)) // need to keep around to produce bridge methods? ...
 		return false;
-	return TypeBinding.equalsEquals(inheritedMethod.returnType, existingMethod.returnType)
-			|| (TypeBinding.notEquals(this.type, existingMethod.declaringClass) // ... not if inheriting the bridge situation from a superclass
-				&& !existingMethod.declaringClass.isInterface()
-				&& areReturnTypesCompatible(existingMethod, inheritedMethod)); // may have to report incompatible return type
+
+	if (!doesMethodOverride(existingMethod, inheritedMethod))
+		return false;
+
+	return TypeBinding.notEquals(this.type, existingMethod.declaringClass) // ... not if inheriting the bridge situation from a superclass
+			&& !existingMethod.declaringClass.isInterface();
 }
 public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) {
 	if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector))