Lines 124-141
Link Here
|
124 |
|
124 |
|
125 |
// so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod |
125 |
// so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod |
126 |
MethodBinding originalInherited = abstractMethod.original(); |
126 |
MethodBinding originalInherited = abstractMethod.original(); |
127 |
if (originalInherited.returnType != concreteMethod.returnType) { |
127 |
if (originalInherited.returnType != concreteMethod.returnType) |
128 |
if (abstractMethod.returnType.leafComponentType().isParameterizedTypeWithActualArguments()) { |
128 |
if (!isAcceptableReturnTypeOverride(concreteMethod, abstractMethod)) |
129 |
if (concreteMethod.returnType.leafComponentType().isRawType()) |
129 |
problemReporter().unsafeReturnTypeOverride(concreteMethod, originalInherited, this.type); |
130 |
problemReporter().unsafeReturnTypeOverride(concreteMethod, originalInherited, this.type); |
130 |
|
131 |
} else if (abstractMethod.hasSubstitutedReturnType() && originalInherited.returnType.leafComponentType().isTypeVariable()) { |
|
|
132 |
if (((TypeVariableBinding) originalInherited.returnType.leafComponentType()).declaringElement == originalInherited) { // see 81618 - type variable from inherited method |
133 |
TypeBinding currentReturnType = concreteMethod.returnType.leafComponentType(); |
134 |
if (!currentReturnType.isTypeVariable() || ((TypeVariableBinding) currentReturnType).declaringElement != concreteMethod) |
135 |
problemReporter().unsafeReturnTypeOverride(concreteMethod, originalInherited, this.type); |
136 |
} |
137 |
} |
138 |
} |
139 |
// check whether bridge method is already defined above for interface methods |
131 |
// check whether bridge method is already defined above for interface methods |
140 |
if (originalInherited.declaringClass.isInterface()) { |
132 |
if (originalInherited.declaringClass.isInterface()) { |
141 |
if ((concreteMethod.declaringClass == this.type.superclass && this.type.superclass.isParameterizedType()) |
133 |
if ((concreteMethod.declaringClass == this.type.superclass && this.type.superclass.isParameterizedType()) |
Lines 150-169
Link Here
|
150 |
|
142 |
|
151 |
// so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod |
143 |
// so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod |
152 |
MethodBinding originalInherited = inheritedMethod.original(); |
144 |
MethodBinding originalInherited = inheritedMethod.original(); |
153 |
if (originalInherited.returnType != currentMethod.returnType) { |
145 |
if (originalInherited.returnType != currentMethod.returnType) |
154 |
// if (currentMethod.returnType.needsUncheckedConversion(inheritedMethod.returnType)) { |
146 |
if (!isAcceptableReturnTypeOverride(currentMethod, inheritedMethod)) |
155 |
// problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); |
|
|
156 |
if (inheritedMethod.returnType.leafComponentType().isParameterizedTypeWithActualArguments() |
157 |
&& currentMethod.returnType.leafComponentType().isRawType()) { |
158 |
problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); |
147 |
problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); |
159 |
} else if (inheritedMethod.hasSubstitutedReturnType() && originalInherited.returnType.leafComponentType().isTypeVariable()) { |
|
|
160 |
if (((TypeVariableBinding) originalInherited.returnType.leafComponentType()).declaringElement == originalInherited) { // see 81618 - type variable from inherited method |
161 |
TypeBinding currentReturnType = currentMethod.returnType.leafComponentType(); |
162 |
if (!currentReturnType.isTypeVariable() || ((TypeVariableBinding) currentReturnType).declaringElement != currentMethod) |
163 |
problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); |
164 |
} |
165 |
} |
166 |
} |
167 |
|
148 |
|
168 |
if (this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()) != null) { |
149 |
if (this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()) != null) { |
169 |
for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) { |
150 |
for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) { |
Lines 586-606
Link Here
|
586 |
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
567 |
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
587 |
return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod); |
568 |
return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod); |
588 |
} |
569 |
} |
589 |
boolean hasGenericParameter(MethodBinding method) { |
|
|
590 |
if (method.genericSignature() == null) return false; |
591 |
|
592 |
// may be only the return type that is generic, need to check parameters |
593 |
TypeBinding[] params = method.parameters; |
594 |
for (int i = 0, l = params.length; i < l; i++) { |
595 |
TypeBinding param = params[i].leafComponentType(); |
596 |
if (param instanceof ReferenceBinding) { |
597 |
int modifiers = ((ReferenceBinding) param).modifiers; |
598 |
if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) |
599 |
return true; |
600 |
} |
601 |
} |
602 |
return false; |
603 |
} |
604 |
boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) { |
570 |
boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) { |
605 |
// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod() |
571 |
// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod() |
606 |
return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding); |
572 |
return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding); |
Lines 674-679
Link Here
|
674 |
} |
640 |
} |
675 |
return copy; |
641 |
return copy; |
676 |
} |
642 |
} |
|
|
643 |
boolean hasGenericParameter(MethodBinding method) { |
644 |
if (method.genericSignature() == null) return false; |
645 |
|
646 |
// may be only the return type that is generic, need to check parameters |
647 |
TypeBinding[] params = method.parameters; |
648 |
for (int i = 0, l = params.length; i < l; i++) { |
649 |
TypeBinding param = params[i].leafComponentType(); |
650 |
if (param instanceof ReferenceBinding) { |
651 |
int modifiers = ((ReferenceBinding) param).modifiers; |
652 |
if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) |
653 |
return true; |
654 |
} |
655 |
} |
656 |
return false; |
657 |
} |
658 |
boolean isAcceptableReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
659 |
// called when currentMethod's return type is compatible with inheritedMethod's return type |
660 |
|
661 |
if (inheritedMethod.declaringClass.isRawType()) |
662 |
return true; // since the inheritedMethod comes from a raw type, the return type is always acceptable |
663 |
|
664 |
TypeBinding currentReturnType = currentMethod.returnType.leafComponentType(); |
665 |
switch (currentReturnType.kind()) { |
666 |
case Binding.RAW_TYPE : |
667 |
return !inheritedMethod.returnType.leafComponentType().isParameterizedTypeWithActualArguments(); |
668 |
case Binding.TYPE_PARAMETER : |
669 |
if (currentReturnType == inheritedMethod.returnType.leafComponentType()) |
670 |
return true; |
671 |
//$FALL-THROUGH$ |
672 |
default : |
673 |
MethodBinding originalInherited = inheritedMethod.original(); |
674 |
TypeBinding originalInheritedReturnType = originalInherited.returnType.leafComponentType(); |
675 |
if (originalInheritedReturnType.isTypeVariable() && ((TypeVariableBinding) originalInheritedReturnType).declaringElement == originalInherited) |
676 |
return false; |
677 |
return true; |
678 |
} |
679 |
} |
677 |
// caveat: returns false if a method is implemented that needs a bridge method |
680 |
// caveat: returns false if a method is implemented that needs a bridge method |
678 |
boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) { |
681 |
boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) { |
679 |
if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface()) |
682 |
if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface()) |
Lines 731-736
Link Here
|
731 |
return method.typeVariables == Binding.NO_TYPE_VARIABLES; |
734 |
return method.typeVariables == Binding.NO_TYPE_VARIABLES; |
732 |
} |
735 |
} |
733 |
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
736 |
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
|
|
737 |
// called when currentMethod's return type is NOT compatible with inheritedMethod's return type |
738 |
|
734 |
// JLS 3 §8.4.5: more are accepted, with an unchecked conversion |
739 |
// JLS 3 §8.4.5: more are accepted, with an unchecked conversion |
735 |
if (currentMethod.returnType == inheritedMethod.returnType.erasure()) { |
740 |
if (currentMethod.returnType == inheritedMethod.returnType.erasure()) { |
736 |
TypeBinding[] currentParams = currentMethod.parameters; |
741 |
TypeBinding[] currentParams = currentMethod.parameters; |