Lines 316-321
Link Here
|
316 |
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) { |
316 |
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) { |
317 |
if (methods[0].declaringClass.isClass()) |
317 |
if (methods[0].declaringClass.isClass()) |
318 |
return super.checkInheritedReturnTypes(methods, length); |
318 |
return super.checkInheritedReturnTypes(methods, length); |
|
|
319 |
if (length <= 1) { |
320 |
return true; // no need to continue since only 1 inherited method is left |
321 |
} |
322 |
// get rid of overriden methods coming from interfaces - if any |
323 |
MethodBinding methodsToCheck[] = new MethodBinding[length]; // must not nullify methods slots in place |
324 |
int count = length; |
325 |
for (int i = 0; i < length; i++) { |
326 |
methodsToCheck[i] = methods[i]; |
327 |
} |
328 |
for (int i = 0; i < length; i++) { |
329 |
MethodBinding existingMethod; |
330 |
if ((existingMethod = methodsToCheck[i]) != null) { |
331 |
for (int j = 0; j < length; j++) { |
332 |
MethodBinding inheritedMethod; |
333 |
if (i != j && (inheritedMethod = methodsToCheck[j]) != null && |
334 |
existingMethod.declaringClass.implementsInterface(inheritedMethod.declaringClass, true)) { |
335 |
MethodBinding substitute = computeSubstituteMethod(inheritedMethod, existingMethod); |
336 |
if (substitute != null && |
337 |
doesSubstituteMethodOverride(existingMethod, substitute) && |
338 |
(existingMethod.returnType.isCompatibleWith(substitute.returnType) || |
339 |
isReturnTypeSubstituable(substitute, existingMethod))) { |
340 |
count--; |
341 |
methodsToCheck[j] = null; |
342 |
} |
343 |
} |
344 |
} |
345 |
} |
346 |
} |
347 |
if (count < length) { |
348 |
if (count == 1) { |
349 |
return true; // no need to continue since only 1 inherited method is left |
350 |
} |
351 |
for (int i = 0, j = 0; j < count; i++) { |
352 |
if (methodsToCheck[i] != null) { |
353 |
methodsToCheck[j++] = methodsToCheck[i]; |
354 |
} |
355 |
} |
356 |
methods = methodsToCheck; |
357 |
length = count; |
358 |
} // else keep methods unchanged for further checks |
319 |
|
359 |
|
320 |
// its possible in 1.5 that A is compatible with B & C, but B is not compatible with C |
360 |
// its possible in 1.5 that A is compatible with B & C, but B is not compatible with C |
321 |
for (int i = 0, l = length - 1; i < l;) { |
361 |
for (int i = 0, l = length - 1; i < l;) { |
Lines 564-569
Link Here
|
564 |
&& inheritedMethod.returnType == existingMethod.returnType |
604 |
&& inheritedMethod.returnType == existingMethod.returnType |
565 |
&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType); |
605 |
&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType); |
566 |
} |
606 |
} |
|
|
607 |
/** |
608 |
* Return true iff the return type of existingMethod is a valid replacement for |
609 |
* the one of substituteMethod in a method declaration, in the context specified |
610 |
* thereafter. It is expected that substituteMethod is the result of the |
611 |
* substitution of the type parameters of an inheritedMethod method according to |
612 |
* the type parameters of existingMethod and the inheritance relationship |
613 |
* between existingMethod's declaring type and inheritedMethod's declaring type, |
614 |
* where inheritedMethod is a method inherited by existingMethod's declaring |
615 |
* type which is override compatible with existingMethod, except maybe for |
616 |
* their respective return types. If those conditions are not met, the result is |
617 |
* unspecified. |
618 |
* @param substituteMethod a proper substitute of a method inherited by existingMethod |
619 |
* @param existingMethod the existing method under examination |
620 |
* @return true if the return type of existingMethod is a valid substitute for |
621 |
* the one of substituteMethod |
622 |
*/ |
623 |
boolean isReturnTypeSubstituable(MethodBinding substituteMethod, MethodBinding existingMethod) { |
624 |
class ReturnTypeSubstitution implements Substitution { |
625 |
TypeBinding replaced, replacer; |
626 |
ReturnTypeSubstitution(TypeBinding replaced, TypeBinding replacer) { |
627 |
this.replaced = replaced; |
628 |
this.replacer = replacer; |
629 |
} |
630 |
public LookupEnvironment environment() { |
631 |
return environment; |
632 |
} |
633 |
public boolean isRawSubstitution() { |
634 |
return false; |
635 |
} |
636 |
public TypeBinding substitute(TypeVariableBinding typeVariable) { |
637 |
return typeVariable == replaced ? replacer : typeVariable; |
638 |
} |
639 |
} |
640 |
if (substituteMethod.returnType instanceof TypeVariableBinding) { |
641 |
return ((TypeVariableBinding) substituteMethod.returnType). |
642 |
boundCheck( |
643 |
new ReturnTypeSubstitution(substituteMethod.returnType, existingMethod.returnType), |
644 |
existingMethod.returnType) == TypeConstants.OK; |
645 |
} else if (substituteMethod.returnType instanceof ParameterizedTypeBinding) { |
646 |
if (! (existingMethod.returnType instanceof ParameterizedTypeBinding)) { |
647 |
return false; |
648 |
} |
649 |
ParameterizedTypeBinding substituteReturnType = (ParameterizedTypeBinding) substituteMethod.returnType, |
650 |
existingReturnType = (ParameterizedTypeBinding) existingMethod.returnType; |
651 |
if (substituteReturnType.type != existingReturnType.type) { |
652 |
return false; |
653 |
} |
654 |
for (int i = 0; i < substituteReturnType.arguments.length; i++) { |
655 |
TypeBinding substituteArgumentType, existingArgumentType; |
656 |
if (! (existingArgumentType = existingReturnType.arguments[i]).isCompatibleWith( |
657 |
substituteArgumentType = substituteReturnType.arguments[i])) { |
658 |
if (substituteArgumentType instanceof TypeVariableBinding) { |
659 |
if (((TypeVariableBinding) substituteArgumentType). |
660 |
boundCheck( |
661 |
new ReturnTypeSubstitution(substituteArgumentType, existingArgumentType), |
662 |
// we do not address the most general pattern of multiple type variables, nor the recursive case either |
663 |
existingArgumentType) != TypeConstants.OK) { |
664 |
return false; |
665 |
} |
666 |
} else { |
667 |
return false; |
668 |
} |
669 |
} |
670 |
} |
671 |
return true; |
672 |
} |
673 |
return false; |
674 |
} |
567 |
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
675 |
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
568 |
ReferenceBinding[] interfacesToVisit = null; |
676 |
ReferenceBinding[] interfacesToVisit = null; |
569 |
int nextPosition = 0; |
677 |
int nextPosition = 0; |