Lines 138-148
Link Here
|
138 |
if (!isAcceptableReturnTypeOverride(currentMethod, inheritedMethod)) |
138 |
if (!isAcceptableReturnTypeOverride(currentMethod, inheritedMethod)) |
139 |
problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); |
139 |
problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, this.type); |
140 |
|
140 |
|
141 |
if (this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()) != null) { |
141 |
MethodBinding bridge = this.type.addSyntheticBridgeMethod(originalInherited, currentMethod.original()); |
|
|
142 |
if (bridge != null) { |
142 |
for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) { |
143 |
for (int i = 0, l = allInheritedMethods == null ? 0 : allInheritedMethods.length; i < l; i++) { |
143 |
if (allInheritedMethods[i] != null && detectInheritedNameClash(originalInherited, allInheritedMethods[i].original())) |
144 |
if (allInheritedMethods[i] != null && detectInheritedNameClash(originalInherited, allInheritedMethods[i].original())) |
144 |
return; |
145 |
return; |
145 |
} |
146 |
} |
|
|
147 |
// See if the new bridge clashes with any of the user methods of the class. For this check |
148 |
// we should check for "method descriptor clash" and not just "method signature clash". Really |
149 |
// what we are checking is whether there is a contention for the method dispatch table slot. |
150 |
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=293615. |
151 |
MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(bridge.selector); |
152 |
for (int i = current.length - 1; i >= 0; --i) { |
153 |
final MethodBinding thisMethod = current[i]; |
154 |
if (thisMethod.areParameterErasuresEqual(bridge) && thisMethod.returnType.erasure() == bridge.returnType.erasure()) { |
155 |
// use inherited method for problem reporting. |
156 |
problemReporter(thisMethod).methodNameClash(thisMethod, inheritedMethod.declaringClass.isRawType() ? inheritedMethod : inheritedMethod.original()); |
157 |
return; |
158 |
} |
159 |
} |
146 |
} |
160 |
} |
147 |
} |
161 |
} |
148 |
void checkForNameClash(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
162 |
void checkForNameClash(MethodBinding currentMethod, MethodBinding inheritedMethod) { |
Lines 180-186
Link Here
|
180 |
|
194 |
|
181 |
if (currentMethod.declaringClass.isInterface() || inheritedMethod.isStatic()) return; |
195 |
if (currentMethod.declaringClass.isInterface() || inheritedMethod.isStatic()) return; |
182 |
|
196 |
|
183 |
if (!detectNameClash(currentMethod, inheritedMethod)) { // check up the hierarchy for skipped inherited methods |
197 |
if (!detectNameClash(currentMethod, inheritedMethod, false)) { // check up the hierarchy for skipped inherited methods |
184 |
TypeBinding[] currentParams = currentMethod.parameters; |
198 |
TypeBinding[] currentParams = currentMethod.parameters; |
185 |
TypeBinding[] inheritedParams = inheritedMethod.parameters; |
199 |
TypeBinding[] inheritedParams = inheritedMethod.parameters; |
186 |
int length = currentParams.length; |
200 |
int length = currentParams.length; |
Lines 204-210
Link Here
|
204 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
218 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
205 |
for (int m = 0, n = methods.length; m < n; m++) { |
219 |
for (int m = 0, n = methods.length; m < n; m++) { |
206 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
220 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
207 |
if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute)) |
221 |
if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute, true)) |
208 |
return; |
222 |
return; |
209 |
} |
223 |
} |
210 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
224 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
Lines 232-238
Link Here
|
232 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
246 |
MethodBinding[] methods = superType.getMethods(currentMethod.selector); |
233 |
for (int m = 0, n = methods.length; m < n; m++){ |
247 |
for (int m = 0, n = methods.length; m < n; m++){ |
234 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
248 |
MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod); |
235 |
if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute)) |
249 |
if (substitute != null && !isSubstituteParameterSubsignature(currentMethod, substitute) && detectNameClash(currentMethod, substitute, true)) |
236 |
return; |
250 |
return; |
237 |
} |
251 |
} |
238 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
252 |
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { |
Lines 555-565
Link Here
|
555 |
problemReporter().inheritedMethodsHaveNameClash(this.type, inherited, otherInherited); |
569 |
problemReporter().inheritedMethodsHaveNameClash(this.type, inherited, otherInherited); |
556 |
return true; |
570 |
return true; |
557 |
} |
571 |
} |
558 |
boolean detectNameClash(MethodBinding current, MethodBinding inherited) { |
572 |
boolean detectNameClash(MethodBinding current, MethodBinding inherited, boolean treatAsSynthetic) { |
559 |
MethodBinding original = inherited.original(); // can be the same as inherited |
573 |
MethodBinding methodToCheck = inherited; |
|
|
574 |
if (!treatAsSynthetic) { |
575 |
// For a user method, see if current class overrides the inherited method. If it does, |
576 |
// then any grievance we may have ought to be against the current class's method and |
577 |
// NOT against any super implementations. https://bugs.eclipse.org/bugs/show_bug.cgi?id=293615 |
578 |
MethodBinding[] currentNamesakes = (MethodBinding[]) this.currentMethods.get(inherited.selector); |
579 |
if (currentNamesakes.length > 1) { // we know it ought to at least one and that current is NOT the override |
580 |
for (int i = 0, length = currentNamesakes.length; i < length; i++) { |
581 |
MethodBinding currentMethod = currentNamesakes[i]; |
582 |
if (currentMethod != current && doesMethodOverride(currentMethod, inherited)) { |
583 |
methodToCheck = currentMethod; |
584 |
break; |
585 |
} |
586 |
} |
587 |
} |
588 |
} |
589 |
MethodBinding original = methodToCheck.original(); // can be the same as inherited |
560 |
if (!current.areParameterErasuresEqual(original)) |
590 |
if (!current.areParameterErasuresEqual(original)) |
561 |
return false; |
591 |
return false; |
562 |
|
592 |
original = inherited.original(); // For error reporting use, inherited.original() |
563 |
problemReporter(current).methodNameClash(current, inherited.declaringClass.isRawType() ? inherited : original); |
593 |
problemReporter(current).methodNameClash(current, inherited.declaringClass.isRawType() ? inherited : original); |
564 |
return true; |
594 |
return true; |
565 |
} |
595 |
} |