Fix for Bug 430310 - [1.8][compiler] Functional interface incorrectly
rejected as not being.

Signed-off-by: Srikanth Sankaran <srikanth_sankaran@in.ibm.com>
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 7e5c6b6..b6a5ef1 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
@@ -4017,6 +4017,89 @@
 			},
 			"null");
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
+public void test430310() {
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"interface Func1<T1, R> {\n" +
+				"        R apply(T1 v1);\n" +
+				"        void other();\n" +
+				"}\n" +
+				"@FunctionalInterface // spurious error: F1<T, R> is not a functional interface\n" +
+				"public interface X<T1, R> extends Func1<T1, R> {\n" +
+				"	default void other() {}\n" +
+				"   public static void main(String [] args) {\n" +
+				"       System.out.println(\"OK\");\n" +
+				"   }\n" +
+				"}\n"
+			},
+			"OK");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
+public void test430310a() {
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"@FunctionalInterface\n" +
+				"public interface X<T1, T2, R> {\n" +
+				"    R apply(T1 v1, T2 v2);\n" +
+				"    default void other() {}\n" +
+				"    public static void main(String[] args) {\n" +
+				"        System.out.println(\"OK\");\n" +
+				"    }\n" +
+				"}\n"
+			},
+			"OK");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
+public void test430310b() {
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"interface I1 {\n" +
+				"	int foo(String s);\n" +
+				"}\n" +
+				"@FunctionalInterface\n" +
+				"interface A1 extends I1 {\n" +
+				"	@Override\n" +
+				"	default int foo(String s) {\n" +
+				"		return -1;\n" +
+				"	}\n" +
+				"	int foo(java.io.Serializable s);\n" +
+				"}\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n"
+			},
+			"OK");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
+public void test430310c() {
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"interface I2 {\n" +
+				"	int foo(String s);\n" +
+				"}\n" +
+				"@FunctionalInterface\n" +
+				"interface A2 extends I2 {\n" +
+				"	@Override\n" +
+				"	default int foo(String s) {\n" +
+				"		return -1;\n" +
+				"	}\n" +
+				"	int bar(java.io.Serializable s);\n" +
+				"}\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n"
+			},
+			"OK");
+}
 
 public static Class testClass() {
 	return LambdaExpressionsTest.class;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
index 3727dbc..c53c769 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
@@ -8963,6 +8963,30 @@
 			"Unhandled exception type Exception\n" + 
 			"----------\n");
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
+public void test430310() {
+	this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"interface Func1<T1, R> {\n" +
+				"        R apply(T1 v1);\n" +
+				"        void other();\n" +
+				"}\n" +
+				"@FunctionalInterface // spurious error: F1<T, R> is not a functional interface\n" +
+				"interface F1<T1, R> extends Func1<T1, R> {\n" +
+				"	default void other() {}\n" +
+				"}\n" +
+				"@FunctionalInterface\n" +
+				"interface F2<T1, R> extends Func1<T1, R> {\n" +
+				"}\n"
+			},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 10)\n" + 
+			"	interface F2<T1, R> extends Func1<T1, R> {\n" + 
+			"	          ^^\n" + 
+			"Invalid \'@FunctionalInterface\' annotation; F2<T1,R> is not a functional interface\n" + 
+			"----------\n");
+}
 public static Class testClass() {
 	return NegativeLambdaExpressionsTest.class;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 75933ff..d3a6ab0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -1867,48 +1867,29 @@
 	int contractsCount = 0;
 	int contractsLength = 0;
 	
-	// -- the following are used for early termination.
-	MethodBinding aContract = null;
-	int contractParameterLength = 0;
-	char [] contractSelector = null;
-	// ---
-	
 	ReferenceBinding [] superInterfaces = superInterfaces();
 	for (int i = 0, length = superInterfaces.length; i < length; i++) {
 		MethodBinding [] superInterfaceContracts = superInterfaces[i].getInterfaceAbstractContracts(scope);
 		final int superInterfaceContractsLength = superInterfaceContracts == null  ? 0 : superInterfaceContracts.length;
-		
 		if (superInterfaceContractsLength == 0) continue;
-		if (aContract == null) {
-			aContract = superInterfaceContracts[0];
-			contractParameterLength = aContract.parameters.length;
-			contractSelector = aContract.selector;
-			contracts = superInterfaceContracts;
-			contractsCount = contractsLength = superInterfaceContractsLength;
-		} else {
-			if (superInterfaceContracts[0].parameters.length != contractParameterLength || !CharOperation.equals(contractSelector, superInterfaceContracts[0].selector)) {
-				throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
-			}
-			if (contractsLength < contractsCount + superInterfaceContractsLength) {
-				System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength = contractsCount + superInterfaceContractsLength], 0, contractsCount);
-			}
-			System.arraycopy(superInterfaceContracts, 0, contracts, contractsCount,	superInterfaceContractsLength);
-			contractsCount += superInterfaceContractsLength;
+		if (contractsLength < contractsCount + superInterfaceContractsLength) {
+			System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength = contractsCount + superInterfaceContractsLength], 0, contractsCount);
 		}
+		System.arraycopy(superInterfaceContracts, 0, contracts, contractsCount,	superInterfaceContractsLength);
+		contractsCount += superInterfaceContractsLength;
 	}
+
 	for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) {
 		final MethodBinding method = methods[i];
-		if (method.isStatic() || method.redeclaresPublicObjectMethod(scope)) continue;
+		if (method == null || method.isStatic() || method.redeclaresPublicObjectMethod(scope)) 
+			continue;
+		if (!method.isValidBinding()) 
+			throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
 		if (method.isDefaultMethod()) {
 			for (int j = 0; j < contractsCount; j++) {
 				if (contracts[j] == null)
 					continue;
 				if (MethodVerifier.doesMethodOverride(method, contracts[j], scope.environment())) {
-					if (aContract == contracts[j]) {
-						aContract = null;
-						contractParameterLength = 0;
-						contractSelector = null;
-					}
 					contractsCount--;
 					// abstract method from super type rendered default by present interface ==> contracts[j] = null;
 					if (j < contractsCount)
@@ -1917,16 +1898,6 @@
 			}
 			continue; // skip default method itself
 		}
-		final boolean validBinding = method.isValidBinding();
-		if (aContract == null && validBinding) {
-			aContract = method;
-			contractParameterLength = aContract.parameters.length;
-			contractSelector = aContract.selector;
-		} else {
-			if (!validBinding || method.parameters.length != contractParameterLength || !CharOperation.equals(contractSelector, method.selector)) {
-				throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
-			}
-		}
 		if (contractsCount == contractsLength) {
 			System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength += 16], 0, contractsCount);
 		}
@@ -1952,15 +1923,32 @@
 	MethodBinding[] methods = null;
 	try {
 		methods = getInterfaceAbstractContracts(scope);
+		if (methods == null || methods.length == 0)
+			return this.singleAbstractMethod[index] = samProblemBinding;
+		int contractParameterLength = 0;
+		char [] contractSelector = null;
+		for (int i = 0, length = methods.length; i < length; i++) {
+			MethodBinding method = methods[i];
+			if (method == null) continue;
+			if (contractSelector == null) {
+				contractSelector = method.selector;
+				contractParameterLength = method.parameters == null ? 0 : method.parameters.length;
+			} else {
+				int methodParameterLength = method.parameters == null ? 0 : method.parameters.length;
+				if (methodParameterLength != contractParameterLength || !CharOperation.equals(method.selector, contractSelector))
+					return this.singleAbstractMethod[index] = samProblemBinding;
+			}
+		}
 	} catch (InvalidInputException e) {
 		return this.singleAbstractMethod[index] = samProblemBinding;
 	}
-	if (methods != null && methods.length == 1)
+	if (methods.length == 1)
 		return this.singleAbstractMethod[index] = methods[0];
 	
 	final LookupEnvironment environment = scope.environment();
 	boolean genericMethodSeen = false;
 	int length = methods.length;
+	
 	next:for (int i = length - 1; i >= 0; --i) {
 		MethodBinding method = methods[i], otherMethod = null;
 		if (method.typeVariables != Binding.NO_TYPE_VARIABLES)