From bdec939be79c133dc4e26837ad9a6b2c7ecd5dda Mon Sep 17 00:00:00 2001 From: paulk Date: Thu, 9 Jul 2015 17:41:18 +1000 Subject: [PATCH] GROOVY-7495: Diamond inheritance of interfaces makes method return type incompatible --- .../codehaus/groovy/classgen/Verifier.java | 6 +-- .../gls/invocation/CovariantReturnTest.groovy | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/main/org/codehaus/groovy/classgen/Verifier.java b/src/main/org/codehaus/groovy/classgen/Verifier.java index 362a19024e9..a107d2442dd 100644 --- a/src/main/org/codehaus/groovy/classgen/Verifier.java +++ b/src/main/org/codehaus/groovy/classgen/Verifier.java @@ -1277,7 +1277,7 @@ private void addCovariantMethods(ClassNode classNode, List declaredMethods, Map } - private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec) { + private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec, Map methodsToAdd) { // method name if (!oldMethod.getName().equals(overridingMethod.getName())) return null; if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0) return null; @@ -1297,7 +1297,7 @@ private MethodNode getCovariantImplementation(final MethodNode oldMethod, final boolean equalReturnType = mr.equals(omr); ClassNode testmr = correctToGenericsSpec(genericsSpec, omr); - if (!isAssignable(mr, testmr)) { + if (!isAssignable(mr, testmr) && !methodsToAdd.containsKey(overridingMethod.getTypeDescriptor())) { throw new RuntimeParserException( "The return type of " + overridingMethod.getTypeDescriptor() + @@ -1418,7 +1418,7 @@ private static ClassNode cleanType(ClassNode type) { private void storeMissingCovariantMethods(Collection methods, MethodNode method, Map methodsToAdd, Map genericsSpec) { for (Object method1 : methods) { MethodNode toOverride = (MethodNode) method1; - MethodNode bridgeMethod = getCovariantImplementation(toOverride, method, genericsSpec); + MethodNode bridgeMethod = getCovariantImplementation(toOverride, method, genericsSpec, methodsToAdd); if (bridgeMethod == null) continue; methodsToAdd.put(bridgeMethod.getTypeDescriptor(), bridgeMethod); return; diff --git a/src/test/gls/invocation/CovariantReturnTest.groovy b/src/test/gls/invocation/CovariantReturnTest.groovy index 96786156eab..b7295c0848c 100644 --- a/src/test/gls/invocation/CovariantReturnTest.groovy +++ b/src/test/gls/invocation/CovariantReturnTest.groovy @@ -267,6 +267,52 @@ public class CovariantReturnTest extends CompilableTestSupport { """ } + void testCovariantMethodGenerics_groovy7495() { + shouldCompile """ + interface A { + B foo() + } + interface B {} + interface A2 extends A { + B2 foo() + } + interface B2 extends B {} + + class AA implements A { + BB foo() { return new BB() } + } + class AA2 extends AA implements A2 { + BB2 foo() { return new BB2() } + } + class BB implements B {} + class BB2 extends BB implements B2 {} + """ + shouldCompile """ + interface Item {} + interface DerivedItem extends Item {} + + interface Base { + Item getItem() + } + class BaseImpl implements Base { + Item getItem() { null } + } + + interface First extends Base { + DerivedItem getItem() + } + + class FirstImpl extends BaseImpl implements First { + DerivedItem getItem() { null } + } + + interface Second extends First {} + class SecondImpl extends FirstImpl implements Second {} + + println FirstImpl.name + """ + } + void testCovariantParameter() { assertScript """ interface Interface {