Details
-
Bug
-
Status: Closed
-
Blocker
-
Resolution: Fixed
-
None
-
None
-
Windows 7
Description
I have two files:
— A.groovy
package p; public class A<T> { }
—
— B.groovy
package p; class B extends A<String> { }
—
Depending on the order in which they are passed to groovyc, I may get an error:
> groovyc A.groovy B.groovy
works fine.
> groovyc B.groovy A.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup
failed, B.groovy: 3: The type String is not a valid substitute for the
bounded parameter <T>
@ line 3, column 17.
class B extends A<String> {
^
1 error
This happens because the generics checking is done as part of the resolution phase. From CompilationUnit:
private final SourceUnitOperation resolve = new SourceUnitOperation() { public void call(SourceUnit source) throws CompilationFailedException { List classes = source.ast.getClasses(); for (Iterator it = classes.iterator(); it.hasNext();) { ClassNode node = (ClassNode) it.next(); VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source); scopeVisitor.visitClass(node); resolveVisitor.startResolving(node, source); GenericsVisitor genericsVisitor = new GenericsVisitor(source); genericsVisitor.visitClass(node); } } };
if the generics check is performed before the types involved (like A) are resolved, you get this problem. The solution is to break that into two phases: resolution and then generics checking (take the last two lines from the resolution phase and move them into a new phase, done after resolution):
/** * Check generics usage */ private final SourceUnitOperation checkGenerics = new SourceUnitOperation() { public void call(SourceUnit source) throws CompilationFailedException { List classes = source.ast.getClasses(); for (Iterator it = classes.iterator(); it.hasNext();) { ClassNode node = (ClassNode) it.next(); GenericsVisitor genericsVisitor = new GenericsVisitor(source); genericsVisitor.visitClass(node); } } };
then the order doesn't matter.