### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java,v retrieving revision 1.71 diff -u -r1.71 MethodVerifier15.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java 28 Mar 2007 04:52:19 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java 29 Mar 2007 07:13:57 -0000 @@ -19,9 +19,9 @@ MethodVerifier15(LookupEnvironment environment) { super(environment); } -boolean areMethodsEqual(MethodBinding one, MethodBinding two) { +boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { MethodBinding sub = computeSubstituteMethod(two, one); - return sub != null && doesSubstituteMethodOverride(one, sub) && areReturnTypesEqual(one, sub); + return sub != null && doesSubstituteMethodOverride(one, sub) && areReturnTypesCompatible(one, sub); } boolean areParametersEqual(MethodBinding one, MethodBinding two) { TypeBinding[] oneArgs = one.parameters; @@ -69,8 +69,9 @@ } return true; } -boolean areReturnTypesEqual(MethodBinding one, MethodBinding substituteTwo) { - return areReturnTypesCompatible(one, substituteTwo); +boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { + if (one.returnType == two.returnType) return true; + return areReturnTypesCompatible0(one, two); } boolean areTypesEqual(TypeBinding one, TypeBinding two) { if (one == two) return true; @@ -293,7 +294,7 @@ MethodBinding[] duplicates = null; for (int j = i + 1; j <= l; j++) { MethodBinding method2 = methods[j]; - if (method.declaringClass == method2.declaringClass && areMethodsEqual(method, method2)) { + if (method.declaringClass == method2.declaringClass && areMethodsCompatible(method, method2)) { skip[j] = -1; if (duplicates == null) duplicates = new MethodBinding[length]; @@ -388,7 +389,7 @@ for (int i = 0, l = length - 1; i < l;) { MethodBinding method = methods[i++]; for (int j = i; j <= l; j++) { - if (!areReturnTypesEqual(method, methods[j])) { + if (!areReturnTypesCompatible(method, methods[j])) { if (this.type.isInterface()) for (int m = length; --m >= 0;) if (methods[m].declaringClass.id == TypeIds.T_JavaLangObject) @@ -502,7 +503,7 @@ if (index > 0) { MethodBinding first = matchingInherited[0]; int count = index + 1; - while (--count > 0 && areReturnTypesEqual(first, matchingInherited[count])){/*empty*/} + while (--count > 0 && areReturnTypesCompatible(first, matchingInherited[count])){/*empty*/} if (count > 0) { // All inherited methods do NOT have the same vmSignature problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(typeParameter, matchingInherited, index + 1); continue nextSelector; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java,v retrieving revision 1.82 diff -u -r1.82 MethodVerifier.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 6 Mar 2007 02:38:51 -0000 1.82 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 29 Mar 2007 07:13:57 -0000 @@ -50,8 +50,8 @@ environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5 && environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5; } -boolean areMethodsEqual(MethodBinding one, MethodBinding two) { - return doesMethodOverride(one, two) && areReturnTypesEqual(one, two); +boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { + return doesMethodOverride(one, two) && areReturnTypesCompatible(one, two); } boolean areParametersEqual(MethodBinding one, MethodBinding two) { TypeBinding[] oneArgs = one.parameters; @@ -65,41 +65,42 @@ if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false; return true; } -boolean areReturnTypesCompatible(MethodBinding one, MethodBinding substituteTwo) { - if (one.returnType == substituteTwo.returnType) return true; +boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { + if (one.returnType == two.returnType) return true; + if (areTypesEqual(one.returnType, two.returnType)) return true; + + // when sourceLevel < 1.5 but compliance >= 1.5, allow return types in binaries to be compatible instead of just equal + if (this.allowCompatibleReturnTypes && + one.declaringClass instanceof BinaryTypeBinding && + two.declaringClass instanceof BinaryTypeBinding) { + return areReturnTypesCompatible0(one, two); + } + return false; +} +boolean areReturnTypesCompatible0(MethodBinding one, MethodBinding two) { // short is compatible with int, but as far as covariance is concerned, its not if (one.returnType.isBaseType()) return false; if (!one.declaringClass.isInterface()) { if (one.declaringClass.id == TypeIds.T_JavaLangObject) - return substituteTwo.returnType.isCompatibleWith(one.returnType); // interface methods inherit from Object - return one.returnType.isCompatibleWith(substituteTwo.returnType); + return two.returnType.isCompatibleWith(one.returnType); // interface methods inherit from Object + return one.returnType.isCompatibleWith(two.returnType); } // check for methods from Object, every interface inherits from Object - if (substituteTwo.declaringClass.id == TypeIds.T_JavaLangObject) - return one.returnType.isCompatibleWith(substituteTwo.returnType); + if (two.declaringClass.id == TypeIds.T_JavaLangObject) + return one.returnType.isCompatibleWith(two.returnType); // both are interfaces, see if they're related - if (one.declaringClass.implementsInterface(substituteTwo.declaringClass, true)) - return one.returnType.isCompatibleWith(substituteTwo.returnType); - if (substituteTwo.declaringClass.implementsInterface(one.declaringClass, true)) - return substituteTwo.returnType.isCompatibleWith(one.returnType); + if (one.declaringClass.implementsInterface(two.declaringClass, true)) + return one.returnType.isCompatibleWith(two.returnType); + if (two.declaringClass.implementsInterface(one.declaringClass, true)) + return two.returnType.isCompatibleWith(one.returnType); // unrelated interfaces... one must be a subtype of the other - return one.returnType.isCompatibleWith(substituteTwo.returnType) - || substituteTwo.returnType.isCompatibleWith(one.returnType); -} -boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) { - if (areTypesEqual(one.returnType, two.returnType)) return true; - - // when sourceLevel < 1.5 but compliance >= 1.5, allow return types in binaries to be compatible instead of just equal - if (this.allowCompatibleReturnTypes) - if (one.declaringClass instanceof BinaryTypeBinding && two.declaringClass instanceof BinaryTypeBinding) - if (areReturnTypesCompatible(one, two)) - return true; - return false; + return one.returnType.isCompatibleWith(two.returnType) + || two.returnType.isCompatibleWith(one.returnType); } boolean areTypesEqual(TypeBinding one, TypeBinding two) { if (one == two) return true; @@ -162,7 +163,7 @@ currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; } - if (!areReturnTypesEqual(currentMethod, inheritedMethod)) + if (!areReturnTypesCompatible(currentMethod, inheritedMethod)) if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) continue nextMethod; @@ -270,7 +271,7 @@ boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) { MethodBinding first = methods[0]; int index = length; - while (--index > 0 && areReturnTypesEqual(first, methods[index])){/*empty*/} + while (--index > 0 && areReturnTypesCompatible(first, methods[index])){/*empty*/} if (index == 0) return true; @@ -382,7 +383,7 @@ MethodBinding method = methods[m]; if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract()) continue nextMethod; - if (areMethodsEqual(method, abstractMethod)) + if (areMethodsCompatible(method, abstractMethod)) return; // found concrete implementation of abstract method in same package } } @@ -459,7 +460,7 @@ MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector); if (existingMethods != null) { for (int i = 0, length = existingMethods.length; i < length; i++) { - if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && areMethodsEqual(existingMethods[i], inheritedMethod)) { + if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethods[i], inheritedMethod)) { if (inheritedMethod.isDefault() && inheritedMethod.isAbstract()) checkPackagePrivateAbstractMethod(inheritedMethod); continue nextMethod; @@ -469,7 +470,7 @@ MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector); if (nonVisible != null) for (int i = 0, l = nonVisible.length; i < l; i++) - if (areMethodsEqual(nonVisible[i], inheritedMethod)) + if (areMethodsCompatible(nonVisible[i], inheritedMethod)) continue nextMethod; if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) { @@ -497,7 +498,7 @@ MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector); if (current != null) { // non visible methods cannot be overridden so a warning is issued foundMatch : for (int i = 0, length = current.length; i < length; i++) { - if (areMethodsEqual(current[i], inheritedMethod)) { + if (areMethodsCompatible(current[i], inheritedMethod)) { problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod); break foundMatch; }