View | Details | Raw Unified | Return to bug 430310
Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java (+83 lines)
Lines 4017-4022 Link Here
4017
			},
4017
			},
4018
			"null");
4018
			"null");
4019
}
4019
}
4020
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
4021
public void test430310() {
4022
	this.runConformTest(
4023
			new String[] {
4024
				"X.java",
4025
				"interface Func1<T1, R> {\n" +
4026
				"        R apply(T1 v1);\n" +
4027
				"        void other();\n" +
4028
				"}\n" +
4029
				"@FunctionalInterface // spurious error: F1<T, R> is not a functional interface\n" +
4030
				"public interface X<T1, R> extends Func1<T1, R> {\n" +
4031
				"	default void other() {}\n" +
4032
				"   public static void main(String [] args) {\n" +
4033
				"       System.out.println(\"OK\");\n" +
4034
				"   }\n" +
4035
				"}\n"
4036
			},
4037
			"OK");
4038
}
4039
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
4040
public void test430310a() {
4041
	this.runConformTest(
4042
			new String[] {
4043
				"X.java",
4044
				"@FunctionalInterface\n" +
4045
				"public interface X<T1, T2, R> {\n" +
4046
				"    R apply(T1 v1, T2 v2);\n" +
4047
				"    default void other() {}\n" +
4048
				"    public static void main(String[] args) {\n" +
4049
				"        System.out.println(\"OK\");\n" +
4050
				"    }\n" +
4051
				"}\n"
4052
			},
4053
			"OK");
4054
}
4055
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
4056
public void test430310b() {
4057
	this.runConformTest(
4058
			new String[] {
4059
				"X.java",
4060
				"interface I1 {\n" +
4061
				"	int foo(String s);\n" +
4062
				"}\n" +
4063
				"@FunctionalInterface\n" +
4064
				"interface A1 extends I1 {\n" +
4065
				"	@Override\n" +
4066
				"	default int foo(String s) {\n" +
4067
				"		return -1;\n" +
4068
				"	}\n" +
4069
				"	int foo(java.io.Serializable s);\n" +
4070
				"}\n" +
4071
				"public class X {\n" +
4072
				"	public static void main(String[] args) {\n" +
4073
				"		System.out.println(\"OK\");\n" +
4074
				"	}\n" +
4075
				"}\n"
4076
			},
4077
			"OK");
4078
}
4079
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
4080
public void test430310c() {
4081
	this.runConformTest(
4082
			new String[] {
4083
				"X.java",
4084
				"interface I2 {\n" +
4085
				"	int foo(String s);\n" +
4086
				"}\n" +
4087
				"@FunctionalInterface\n" +
4088
				"interface A2 extends I2 {\n" +
4089
				"	@Override\n" +
4090
				"	default int foo(String s) {\n" +
4091
				"		return -1;\n" +
4092
				"	}\n" +
4093
				"	int bar(java.io.Serializable s);\n" +
4094
				"}\n" +
4095
				"public class X {\n" +
4096
				"	public static void main(String[] args) {\n" +
4097
				"		System.out.println(\"OK\");\n" +
4098
				"	}\n" +
4099
				"}\n"
4100
			},
4101
			"OK");
4102
}
4020
4103
4021
public static Class testClass() {
4104
public static Class testClass() {
4022
	return LambdaExpressionsTest.class;
4105
	return LambdaExpressionsTest.class;
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java (+24 lines)
Lines 8963-8968 Link Here
8963
			"Unhandled exception type Exception\n" + 
8963
			"Unhandled exception type Exception\n" + 
8964
			"----------\n");
8964
			"----------\n");
8965
}
8965
}
8966
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430310, [1.8][compiler] Functional interface incorrectly rejected as not being.
8967
public void test430310() {
8968
	this.runNegativeTest(
8969
			new String[] {
8970
				"X.java",
8971
				"interface Func1<T1, R> {\n" +
8972
				"        R apply(T1 v1);\n" +
8973
				"        void other();\n" +
8974
				"}\n" +
8975
				"@FunctionalInterface // spurious error: F1<T, R> is not a functional interface\n" +
8976
				"interface F1<T1, R> extends Func1<T1, R> {\n" +
8977
				"	default void other() {}\n" +
8978
				"}\n" +
8979
				"@FunctionalInterface\n" +
8980
				"interface F2<T1, R> extends Func1<T1, R> {\n" +
8981
				"}\n"
8982
			},
8983
			"----------\n" + 
8984
			"1. ERROR in X.java (at line 10)\n" + 
8985
			"	interface F2<T1, R> extends Func1<T1, R> {\n" + 
8986
			"	          ^^\n" + 
8987
			"Invalid \'@FunctionalInterface\' annotation; F2<T1,R> is not a functional interface\n" + 
8988
			"----------\n");
8989
}
8966
public static Class testClass() {
8990
public static Class testClass() {
8967
	return NegativeLambdaExpressionsTest.class;
8991
	return NegativeLambdaExpressionsTest.class;
8968
}
8992
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (-39 / +27 lines)
Lines 1867-1914 Link Here
1867
	int contractsCount = 0;
1867
	int contractsCount = 0;
1868
	int contractsLength = 0;
1868
	int contractsLength = 0;
1869
	
1869
	
1870
	// -- the following are used for early termination.
1871
	MethodBinding aContract = null;
1872
	int contractParameterLength = 0;
1873
	char [] contractSelector = null;
1874
	// ---
1875
	
1876
	ReferenceBinding [] superInterfaces = superInterfaces();
1870
	ReferenceBinding [] superInterfaces = superInterfaces();
1877
	for (int i = 0, length = superInterfaces.length; i < length; i++) {
1871
	for (int i = 0, length = superInterfaces.length; i < length; i++) {
1878
		MethodBinding [] superInterfaceContracts = superInterfaces[i].getInterfaceAbstractContracts(scope);
1872
		MethodBinding [] superInterfaceContracts = superInterfaces[i].getInterfaceAbstractContracts(scope);
1879
		final int superInterfaceContractsLength = superInterfaceContracts == null  ? 0 : superInterfaceContracts.length;
1873
		final int superInterfaceContractsLength = superInterfaceContracts == null  ? 0 : superInterfaceContracts.length;
1880
		
1881
		if (superInterfaceContractsLength == 0) continue;
1874
		if (superInterfaceContractsLength == 0) continue;
1882
		if (aContract == null) {
1875
		if (contractsLength < contractsCount + superInterfaceContractsLength) {
1883
			aContract = superInterfaceContracts[0];
1876
			System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength = contractsCount + superInterfaceContractsLength], 0, contractsCount);
1884
			contractParameterLength = aContract.parameters.length;
1885
			contractSelector = aContract.selector;
1886
			contracts = superInterfaceContracts;
1887
			contractsCount = contractsLength = superInterfaceContractsLength;
1888
		} else {
1889
			if (superInterfaceContracts[0].parameters.length != contractParameterLength || !CharOperation.equals(contractSelector, superInterfaceContracts[0].selector)) {
1890
				throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
1891
			}
1892
			if (contractsLength < contractsCount + superInterfaceContractsLength) {
1893
				System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength = contractsCount + superInterfaceContractsLength], 0, contractsCount);
1894
			}
1895
			System.arraycopy(superInterfaceContracts, 0, contracts, contractsCount,	superInterfaceContractsLength);
1896
			contractsCount += superInterfaceContractsLength;
1897
		}
1877
		}
1878
		System.arraycopy(superInterfaceContracts, 0, contracts, contractsCount,	superInterfaceContractsLength);
1879
		contractsCount += superInterfaceContractsLength;
1898
	}
1880
	}
1881
1899
	for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) {
1882
	for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) {
1900
		final MethodBinding method = methods[i];
1883
		final MethodBinding method = methods[i];
1901
		if (method.isStatic() || method.redeclaresPublicObjectMethod(scope)) continue;
1884
		if (method == null || method.isStatic() || method.redeclaresPublicObjectMethod(scope)) 
1885
			continue;
1886
		if (!method.isValidBinding()) 
1887
			throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
1902
		if (method.isDefaultMethod()) {
1888
		if (method.isDefaultMethod()) {
1903
			for (int j = 0; j < contractsCount; j++) {
1889
			for (int j = 0; j < contractsCount; j++) {
1904
				if (contracts[j] == null)
1890
				if (contracts[j] == null)
1905
					continue;
1891
					continue;
1906
				if (MethodVerifier.doesMethodOverride(method, contracts[j], scope.environment())) {
1892
				if (MethodVerifier.doesMethodOverride(method, contracts[j], scope.environment())) {
1907
					if (aContract == contracts[j]) {
1908
						aContract = null;
1909
						contractParameterLength = 0;
1910
						contractSelector = null;
1911
					}
1912
					contractsCount--;
1893
					contractsCount--;
1913
					// abstract method from super type rendered default by present interface ==> contracts[j] = null;
1894
					// abstract method from super type rendered default by present interface ==> contracts[j] = null;
1914
					if (j < contractsCount)
1895
					if (j < contractsCount)
Lines 1916-1931 Link Here
1916
				}
1897
				}
1917
			}
1898
			}
1918
			continue; // skip default method itself
1899
			continue; // skip default method itself
1919
		}
1920
		final boolean validBinding = method.isValidBinding();
1921
		if (aContract == null && validBinding) {
1922
			aContract = method;
1923
			contractParameterLength = aContract.parameters.length;
1924
			contractSelector = aContract.selector;
1925
		} else {
1926
			if (!validBinding || method.parameters.length != contractParameterLength || !CharOperation.equals(contractSelector, method.selector)) {
1927
				throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
1928
			}
1929
		}
1900
		}
1930
		if (contractsCount == contractsLength) {
1901
		if (contractsCount == contractsLength) {
1931
			System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength += 16], 0, contractsCount);
1902
			System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength += 16], 0, contractsCount);
Lines 1952-1966 Link Here
1952
	MethodBinding[] methods = null;
1923
	MethodBinding[] methods = null;
1953
	try {
1924
	try {
1954
		methods = getInterfaceAbstractContracts(scope);
1925
		methods = getInterfaceAbstractContracts(scope);
1926
		if (methods == null || methods.length == 0)
1927
			return this.singleAbstractMethod[index] = samProblemBinding;
1928
		int contractParameterLength = 0;
1929
		char [] contractSelector = null;
1930
		for (int i = 0, length = methods.length; i < length; i++) {
1931
			MethodBinding method = methods[i];
1932
			if (method == null) continue;
1933
			if (contractSelector == null) {
1934
				contractSelector = method.selector;
1935
				contractParameterLength = method.parameters == null ? 0 : method.parameters.length;
1936
			} else {
1937
				int methodParameterLength = method.parameters == null ? 0 : method.parameters.length;
1938
				if (methodParameterLength != contractParameterLength || !CharOperation.equals(method.selector, contractSelector))
1939
					return this.singleAbstractMethod[index] = samProblemBinding;
1940
			}
1941
		}
1955
	} catch (InvalidInputException e) {
1942
	} catch (InvalidInputException e) {
1956
		return this.singleAbstractMethod[index] = samProblemBinding;
1943
		return this.singleAbstractMethod[index] = samProblemBinding;
1957
	}
1944
	}
1958
	if (methods != null && methods.length == 1)
1945
	if (methods.length == 1)
1959
		return this.singleAbstractMethod[index] = methods[0];
1946
		return this.singleAbstractMethod[index] = methods[0];
1960
	
1947
	
1961
	final LookupEnvironment environment = scope.environment();
1948
	final LookupEnvironment environment = scope.environment();
1962
	boolean genericMethodSeen = false;
1949
	boolean genericMethodSeen = false;
1963
	int length = methods.length;
1950
	int length = methods.length;
1951
	
1964
	next:for (int i = length - 1; i >= 0; --i) {
1952
	next:for (int i = length - 1; i >= 0; --i) {
1965
		MethodBinding method = methods[i], otherMethod = null;
1953
		MethodBinding method = methods[i], otherMethod = null;
1966
		if (method.typeVariables != Binding.NO_TYPE_VARIABLES)
1954
		if (method.typeVariables != Binding.NO_TYPE_VARIABLES)

Return to bug 430310