Skip to content

Commit fc776ff

Browse files
committed
GROOVY-11579: skip bridge method in final method override checking
1 parent 43d4f93 commit fc776ff

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed

src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java

+18-15
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import static org.objectweb.asm.Opcodes.ACC_STATIC;
7575
import static org.objectweb.asm.Opcodes.ACC_STRICT;
7676
import static org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED;
77+
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
7778
import static org.objectweb.asm.Opcodes.ACC_TRANSIENT;
7879
import static org.objectweb.asm.Opcodes.ACC_VOLATILE;
7980

@@ -404,26 +405,27 @@ private void checkMethodsForWeakerAccess(final ClassNode cn) {
404405

405406
private void checkMethodsForOverridingFinal(final ClassNode cn) {
406407
for (MethodNode method : cn.getMethods()) {
408+
if ((method.getModifiers() & ACC_SYNTHETIC) != 0) continue; // GROOVY-11579: bridge method
409+
410+
ClassNode sc = cn.getSuperClass();
407411
Parameter[] params = method.getParameters();
408-
for (MethodNode superMethod : cn.getSuperClass().getMethods(method.getName())) {
409-
Parameter[] superParams = superMethod.getParameters();
410-
if (!ParameterUtils.parametersEqual(params, superParams)) continue;
411-
if (!superMethod.isFinal()) break;
412-
addInvalidUseOfFinalError(method, params, superMethod.getDeclaringClass());
413-
return;
412+
for (MethodNode superMethod : sc.getMethods(method.getName())) {
413+
if (superMethod.isFinal()
414+
&& ParameterUtils.parametersEqual(params, superMethod.getParameters())) {
415+
StringBuilder sb = new StringBuilder();
416+
sb.append("You are not allowed to override the final method ");
417+
sb.append(method.getName());
418+
appendParamsDescription(params, sb);
419+
sb.append(" from ");
420+
sb.append(getDescription(sc));
421+
sb.append(".");
422+
423+
addError(sb.toString(), method.getLineNumber() > 0 ? method : cn);
424+
}
414425
}
415426
}
416427
}
417428

418-
private void addInvalidUseOfFinalError(final MethodNode method, final Parameter[] parameters, final ClassNode superCN) {
419-
StringBuilder msg = new StringBuilder();
420-
msg.append("You are not allowed to override the final method ").append(method.getName());
421-
appendParamsDescription(parameters, msg);
422-
msg.append(" from ").append(getDescription(superCN));
423-
msg.append(".");
424-
addError(msg.toString(), method);
425-
}
426-
427429
private void appendParamsDescription(final Parameter[] parameters, final StringBuilder msg) {
428430
msg.append('(');
429431
boolean needsComma = false;
@@ -450,6 +452,7 @@ private void addWeakerAccessError(final ClassNode cn, final MethodNode method, f
450452
msg.append(superMethod.getDeclaringClass().getName());
451453
msg.append("; attempting to assign weaker access privileges; was ");
452454
msg.append(superMethod.isPublic() ? "public" : (superMethod.isProtected() ? "protected" : "package-private"));
455+
453456
addError(msg.toString(), method);
454457
}
455458

src/test/groovy/OverrideTest.groovy

+17
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,23 @@ final class OverrideTest {
225225
'''
226226
}
227227

228+
// GROOVY-11579
229+
@Test
230+
void testCovariantReturnType() {
231+
assertScript '''
232+
interface I<T> {
233+
T m()
234+
}
235+
abstract class A {
236+
final String m() { 'A' }
237+
}
238+
class C extends A implements I<String> {
239+
}
240+
241+
assert new C().m() == 'A'
242+
'''
243+
}
244+
228245
@Test
229246
void testOverrideOnMethodWithDefaultParameters() {
230247
assertScript '''

0 commit comments

Comments
 (0)