The closure parameter of the main type is anomaly

In the following code, why Groovy seems to ignore the provided declaration of the universal closing parameter type in the barMany method:

 import groovy.transform.CompileStatic @CompileStatic class Main { static main(args) { FooSub foo = new FooSub() BarSub bar = new BarSub() } } @CompileStatic class Foo<T> { void fooOne (T item) {} void fooMany(List<T> items) { items.each { T item -> fooOne(item) } // Compiles fine. } } @CompileStatic class FooSub extends Foo<Integer> {} @CompileStatic class Bar<T extends Bar<T>> { void barOne (T item) {} void barMany(List<T> items) { items.each { T item -> barOne(item) } // Error: // Cannot find matching method Bar#barOne(java.lang.Object) !!! items.each { T item -> barOne(item as T) } // Error: // Expected parameter of type java.lang.Object but got T !!! items.each { item -> barOne(item as T) } // Compiles fine - closure knows about T } void barManyMore(List<T> items) { for (T item in items) { // Compiles fine. barOne(item) } } } @CompileStatic class BarSub extends Bar<BarSub> {} 

Update : Groovy Version: 2.4.5 JVM: 1.7.0_80 Supplier: Oracle Corporation OS: Linux

Update So, there was this strange error that I had not noticed before - org.codehaus.groovy.control.MultipleCompilationErrorsException: the launch failed, I will print the full output:

 ~/grov/tests$ groovyc generics.groovy org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: generics.groovy: 27: Expected parameter of type java.lang.Object but got T @ line 27, column 19. items.each { T item -> barOne(item) } // Error: ^ generics.groovy: 27: [Static type checking] - Cannot find matching method Bar#barOne(java.lang.Object). Please check if the declared type is right and if the method exists. @ line 27, column 29. items.each { T item -> barOne(item) } // Error: ^ generics.groovy: 30: Expected parameter of type java.lang.Object but got T @ line 30, column 22. items.each { T item -> barOne(item as T) } // Error: ^ 3 errors ~/grov/tests$ groovyc -v Groovy compiler version 2.4.5 Copyright 2003-2015 The Apache Software Foundation. http://groovy-lang.org/ 

Update

A few additional solutions for completeness: These workarounds seem to work:

  Closure c = { T item -> barOne(item) }; items.each c // See comments by @tim_yates items.each ( { T item -> barOne(item) } as Closure) // Casting to closure works too! 

The same problem also applies when a type has a class based on a common T:

 @CompileStatic class Baz<T extends Baz<T>> { List<T> getList() { return [new T(), new T()] } } @CompileStatic class BazClient { void useBaz(Baz baz) { // baz.getList().each {Baz it -> println it} // Error Closure c = {Baz it -> println it}; baz.getList().each c // works baz.getList().each ({Baz it -> println it} as Closure) // works } } 
+7
closures generics groovy
source share
1 answer

This was one of the generic errors that were fixed in Groovy 2.4.6.

0
source share

All Articles