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

(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (-7 / +8 lines)
Lines 19-27 Link Here
19
MethodVerifier15(LookupEnvironment environment) {
19
MethodVerifier15(LookupEnvironment environment) {
20
	super(environment);
20
	super(environment);
21
}
21
}
22
boolean areMethodsEqual(MethodBinding one, MethodBinding two) {
22
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
23
	MethodBinding sub = computeSubstituteMethod(two, one);
23
	MethodBinding sub = computeSubstituteMethod(two, one);
24
	return sub != null && doesSubstituteMethodOverride(one, sub) && areReturnTypesEqual(one, sub);
24
	return sub != null && doesSubstituteMethodOverride(one, sub) && areReturnTypesCompatible(one, sub);
25
}
25
}
26
boolean areParametersEqual(MethodBinding one, MethodBinding two) {
26
boolean areParametersEqual(MethodBinding one, MethodBinding two) {
27
	TypeBinding[] oneArgs = one.parameters;
27
	TypeBinding[] oneArgs = one.parameters;
Lines 69-76 Link Here
69
	}
69
	}
70
	return true;
70
	return true;
71
}
71
}
72
boolean areReturnTypesEqual(MethodBinding one, MethodBinding substituteTwo) {
72
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) {
73
	return areReturnTypesCompatible(one, substituteTwo);
73
	if (one.returnType == two.returnType) return true;
74
	return areReturnTypesCompatible0(one, two);
74
}
75
}
75
boolean areTypesEqual(TypeBinding one, TypeBinding two) {
76
boolean areTypesEqual(TypeBinding one, TypeBinding two) {
76
	if (one == two) return true;
77
	if (one == two) return true;
Lines 293-299 Link Here
293
		MethodBinding[] duplicates = null;
294
		MethodBinding[] duplicates = null;
294
		for (int j = i + 1; j <= l; j++) {
295
		for (int j = i + 1; j <= l; j++) {
295
			MethodBinding method2 = methods[j];
296
			MethodBinding method2 = methods[j];
296
			if (method.declaringClass == method2.declaringClass && areMethodsEqual(method, method2)) {
297
			if (method.declaringClass == method2.declaringClass && areMethodsCompatible(method, method2)) {
297
				skip[j] = -1;
298
				skip[j] = -1;
298
				if (duplicates == null)
299
				if (duplicates == null)
299
					duplicates = new MethodBinding[length];
300
					duplicates = new MethodBinding[length];
Lines 388-394 Link Here
388
	for (int i = 0, l = length - 1; i < l;) {
389
	for (int i = 0, l = length - 1; i < l;) {
389
		MethodBinding method = methods[i++];
390
		MethodBinding method = methods[i++];
390
		for (int j = i; j <= l; j++) {
391
		for (int j = i; j <= l; j++) {
391
			if (!areReturnTypesEqual(method, methods[j])) {
392
			if (!areReturnTypesCompatible(method, methods[j])) {
392
				if (this.type.isInterface())
393
				if (this.type.isInterface())
393
					for (int m = length; --m >= 0;)
394
					for (int m = length; --m >= 0;)
394
						if (methods[m].declaringClass.id == TypeIds.T_JavaLangObject)
395
						if (methods[m].declaringClass.id == TypeIds.T_JavaLangObject)
Lines 502-508 Link Here
502
			if (index > 0) {
503
			if (index > 0) {
503
				MethodBinding first = matchingInherited[0];
504
				MethodBinding first = matchingInherited[0];
504
				int count = index + 1;
505
				int count = index + 1;
505
				while (--count > 0 && areReturnTypesEqual(first, matchingInherited[count])){/*empty*/}
506
				while (--count > 0 && areReturnTypesCompatible(first, matchingInherited[count])){/*empty*/}
506
				if (count > 0) {  // All inherited methods do NOT have the same vmSignature
507
				if (count > 0) {  // All inherited methods do NOT have the same vmSignature
507
					problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(typeParameter, matchingInherited, index + 1);
508
					problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(typeParameter, matchingInherited, index + 1);
508
					continue nextSelector;
509
					continue nextSelector;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java (-30 / +31 lines)
Lines 50-57 Link Here
50
		environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5
50
		environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5
51
			&& environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5;
51
			&& environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5;
52
}
52
}
53
boolean areMethodsEqual(MethodBinding one, MethodBinding two) {
53
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
54
	return doesMethodOverride(one, two) && areReturnTypesEqual(one, two);
54
	return doesMethodOverride(one, two) && areReturnTypesCompatible(one, two);
55
}
55
}
56
boolean areParametersEqual(MethodBinding one, MethodBinding two) {
56
boolean areParametersEqual(MethodBinding one, MethodBinding two) {
57
	TypeBinding[] oneArgs = one.parameters;
57
	TypeBinding[] oneArgs = one.parameters;
Lines 65-105 Link Here
65
		if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
65
		if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
66
	return true;
66
	return true;
67
}
67
}
68
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding substituteTwo) {
68
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) {
69
	if (one.returnType == substituteTwo.returnType) return true;
69
	if (one.returnType == two.returnType) return true;
70
70
71
	if (areTypesEqual(one.returnType, two.returnType)) return true;
72
	
73
	// when sourceLevel < 1.5 but compliance >= 1.5, allow return types in binaries to be compatible instead of just equal
74
	if (this.allowCompatibleReturnTypes &&
75
			one.declaringClass instanceof BinaryTypeBinding &&
76
			two.declaringClass instanceof BinaryTypeBinding) {
77
		return areReturnTypesCompatible0(one, two);
78
	}
79
	return false;
80
}
81
boolean areReturnTypesCompatible0(MethodBinding one, MethodBinding two) {
71
	// short is compatible with int, but as far as covariance is concerned, its not
82
	// short is compatible with int, but as far as covariance is concerned, its not
72
	if (one.returnType.isBaseType()) return false;
83
	if (one.returnType.isBaseType()) return false;
73
84
74
	if (!one.declaringClass.isInterface()) {
85
	if (!one.declaringClass.isInterface()) {
75
		if (one.declaringClass.id == TypeIds.T_JavaLangObject)
86
		if (one.declaringClass.id == TypeIds.T_JavaLangObject)
76
			return substituteTwo.returnType.isCompatibleWith(one.returnType); // interface methods inherit from Object
87
			return two.returnType.isCompatibleWith(one.returnType); // interface methods inherit from Object
77
		return one.returnType.isCompatibleWith(substituteTwo.returnType);
88
		return one.returnType.isCompatibleWith(two.returnType);
78
	}
89
	}
79
90
80
	// check for methods from Object, every interface inherits from Object
91
	// check for methods from Object, every interface inherits from Object
81
	if (substituteTwo.declaringClass.id == TypeIds.T_JavaLangObject)
92
	if (two.declaringClass.id == TypeIds.T_JavaLangObject)
82
		return one.returnType.isCompatibleWith(substituteTwo.returnType);
93
		return one.returnType.isCompatibleWith(two.returnType);
83
94
84
	// both are interfaces, see if they're related
95
	// both are interfaces, see if they're related
85
	if (one.declaringClass.implementsInterface(substituteTwo.declaringClass, true))
96
	if (one.declaringClass.implementsInterface(two.declaringClass, true))
86
		return one.returnType.isCompatibleWith(substituteTwo.returnType);
97
		return one.returnType.isCompatibleWith(two.returnType);
87
	if (substituteTwo.declaringClass.implementsInterface(one.declaringClass, true))
98
	if (two.declaringClass.implementsInterface(one.declaringClass, true))
88
		return substituteTwo.returnType.isCompatibleWith(one.returnType);
99
		return two.returnType.isCompatibleWith(one.returnType);
89
100
90
	// unrelated interfaces... one must be a subtype of the other
101
	// unrelated interfaces... one must be a subtype of the other
91
	return one.returnType.isCompatibleWith(substituteTwo.returnType)
102
	return one.returnType.isCompatibleWith(two.returnType)
92
		|| substituteTwo.returnType.isCompatibleWith(one.returnType);
103
		|| two.returnType.isCompatibleWith(one.returnType);
93
}
94
boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
95
	if (areTypesEqual(one.returnType, two.returnType)) return true;
96
97
	// when sourceLevel < 1.5 but compliance >= 1.5, allow return types in binaries to be compatible instead of just equal
98
	if (this.allowCompatibleReturnTypes)
99
		if (one.declaringClass instanceof BinaryTypeBinding && two.declaringClass instanceof BinaryTypeBinding)
100
			if (areReturnTypesCompatible(one, two))
101
				return true;
102
	return false;
103
}
104
}
104
boolean areTypesEqual(TypeBinding one, TypeBinding two) {
105
boolean areTypesEqual(TypeBinding one, TypeBinding two) {
105
	if (one == two) return true;
106
	if (one == two) return true;
Lines 162-168 Link Here
162
			currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding;
163
			currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding;
163
		}
164
		}
164
165
165
		if (!areReturnTypesEqual(currentMethod, inheritedMethod))
166
		if (!areReturnTypesCompatible(currentMethod, inheritedMethod))
166
			if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod))
167
			if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod))
167
				continue nextMethod;
168
				continue nextMethod;
168
169
Lines 270-276 Link Here
270
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) {
271
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) {
271
	MethodBinding first = methods[0];
272
	MethodBinding first = methods[0];
272
	int index = length;
273
	int index = length;
273
	while (--index > 0 && areReturnTypesEqual(first, methods[index])){/*empty*/}
274
	while (--index > 0 && areReturnTypesCompatible(first, methods[index])){/*empty*/}
274
	if (index == 0) 
275
	if (index == 0) 
275
		return true;
276
		return true;
276
277
Lines 382-388 Link Here
382
				MethodBinding method = methods[m];
383
				MethodBinding method = methods[m];
383
				if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
384
				if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
384
					continue nextMethod;
385
					continue nextMethod;
385
				if (areMethodsEqual(method, abstractMethod))
386
				if (areMethodsCompatible(method, abstractMethod))
386
					return; // found concrete implementation of abstract method in same package
387
					return; // found concrete implementation of abstract method in same package
387
			}
388
			}
388
		}
389
		}
Lines 459-465 Link Here
459
			MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
460
			MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
460
			if (existingMethods != null) {
461
			if (existingMethods != null) {
461
				for (int i = 0, length = existingMethods.length; i < length; i++) {
462
				for (int i = 0, length = existingMethods.length; i < length; i++) {
462
					if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && areMethodsEqual(existingMethods[i], inheritedMethod)) {
463
					if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethods[i], inheritedMethod)) {
463
						if (inheritedMethod.isDefault() && inheritedMethod.isAbstract())
464
						if (inheritedMethod.isDefault() && inheritedMethod.isAbstract())
464
							checkPackagePrivateAbstractMethod(inheritedMethod);
465
							checkPackagePrivateAbstractMethod(inheritedMethod);
465
						continue nextMethod;
466
						continue nextMethod;
Lines 469-475 Link Here
469
			MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector);
470
			MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector);
470
			if (nonVisible != null)
471
			if (nonVisible != null)
471
				for (int i = 0, l = nonVisible.length; i < l; i++)
472
				for (int i = 0, l = nonVisible.length; i < l; i++)
472
					if (areMethodsEqual(nonVisible[i], inheritedMethod))
473
					if (areMethodsCompatible(nonVisible[i], inheritedMethod))
473
						continue nextMethod;
474
						continue nextMethod;
474
475
475
			if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) {
476
			if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) {
Lines 497-503 Link Here
497
				MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector);
498
				MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector);
498
				if (current != null) { // non visible methods cannot be overridden so a warning is issued
499
				if (current != null) { // non visible methods cannot be overridden so a warning is issued
499
					foundMatch : for (int i = 0, length = current.length; i < length; i++) {
500
					foundMatch : for (int i = 0, length = current.length; i < length; i++) {
500
						if (areMethodsEqual(current[i], inheritedMethod)) {
501
						if (areMethodsCompatible(current[i], inheritedMethod)) {
501
							problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod);
502
							problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod);
502
							break foundMatch;
503
							break foundMatch;
503
						}
504
						}

Return to bug 162370