Octavia Togami created GROOVY-12203:
---------------------------------------

             Summary: False positive "name clash" for a valid override when a 
`? super` wildcard uses a type that declares the same type variable name
                 Key: GROOVY-12203
                 URL: https://issues.apache.org/jira/browse/GROOVY-12203
             Project: Groovy
          Issue Type: Bug
          Components: Compiler
    Affects Versions: 5.0.7
            Reporter: Octavia Togami


The following code in a `Repro.groovy` will cause the error:
{code:groovy}
interface Box<T> { }

interface Spec {
    <T extends Number> void m(Box<? super T> b)
}

class Impl implements Spec {
    @Override
    <T extends Number> void m(Box<? super T> b) { }
}
{code}
{code:sh}
$ groovyc Repro.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Repro.groovy: 8: name clash: m(Box<? super T>) in class 'Impl' and m(Box<? 
super T>) in interface 'Spec' have the same erasure, yet neither overrides the 
other.
 @ line 8, column 5.
       @Override
       ^

1 error
{code}
The two signatures in the message are identical. This worked fine in Groovy 4 
and compiles
under {{javac}} as well.

Renaming {{{}Box{}}}'s own type variable fixes it, with nothing else changed:
{code:groovy}
interface Box<X> { }
{code}
So the check appears to be keying on the name.

Only the interface side matters. If the interface declares
{{<D extends Number> void m(Box<? super D> b)}} and the class declares
{{{}<T extends Number> void m(Box<? super T> b){}}}, it compiles.

Because it keys on the name, whether a type trips it depends on what that type 
happens to
call its own type variable. With a method variable named {{{}T{}}}, 
{{{}Consumer{}}}, {{{}Supplier{}}},
{{{}Function{}}}, {{Comparator}} and {{Iterable}} all fail, while 
{{{}List<E>{}}}, {{Collection<E>}}
and {{Callable<V>}} are fine. {{List}} fails too once the method variable is 
renamed to {{{}E{}}}.

It also does not matter whether the supertype is a Java interface, a Groovy 
interface or a
Groovy abstract class, or whether it is precompiled.

This bisects to 5.0.0-beta-1: 5.0.0-alpha-12 compiles it and 5.0.0-beta-1 does 
not. That is
the fix version of GROOVY-11550, which added
{{ClassCompletionVerifier#checkMethodsForOverridingIssue}} in
[https://github.com/apache/groovy/commit/a3c59394977fd9feb5220812f62b6fd0b60a0739].
 That seems likely to be the cause of the issue in some manner.

This was shrunk from real code in Gradle. 
{{org.gradle.api.problems.ProblemSpec}} declares:
{code:java}
<T extends AdditionalData> ProblemSpec additionalData(Class<T> type, Action<? 
super T> config);
{code}
and {{org.gradle.api.Action}} also names its type variable {{{}T{}}}, so no 
Groovy 5 class can
implement it.

[https://github.com/gradle/gradle/blob/216ed75ae0d82b8bd1fdd3880f7e752f58e7aba9/platforms/ide/problems-api/src/main/java/org/gradle/api/problems/ProblemSpec.java#L162]



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to