codeconsole opened a new pull request, #3089:
URL: https://github.com/apache/groovy/pull/3089

   Under `@CompileStatic`, a closure passed for a parameter declared with a 
type parameter was passed unconverted when the call binds the type parameter to 
a functional interface. The type checker accepted the call, but the writer cast 
the argument to the erasure of the parameter type, so the closure itself was 
stored and a later call of the interface method failed:
   
   ```groovy
   @CompileStatic
   String f() {
       List<Supplier<String>> list = []
       list.add { 'x' }
       list[0].get() // ClassCastException: _f_closure1 cannot be cast to 
java.util.function.Supplier
   }
   ```
   
   The same held for `map.put('k') { ... }` on a `Map<String, Function<String, 
String>>`, `set`, `putIfAbsent`, `AtomicReference.set`, a constructor argument 
of a parameterized type, `list << { ... }`, the varargs of 
`Collections.addAll`, and a variable or conditional expression of type 
`Closure`. For `<T extends Function<String, String>> T second(T a, T b)` called 
with a `Shout` (a subinterface of `Function`) and a closure, the closure became 
a `Function` and the cast of the result to `Shout` failed. The type checker 
also did not take the parameter for a functional interface: it inferred no 
parameter types for the closure (`it.toUpperCase()` was rejected), compiled a 
lambda for it as a closure, and rejected a method reference with "parameter 
type 'E' is not a functional interface", which is GROOVY-10979.
   
   The type checker now resolves such a parameter type for the call, as it does 
the return type, from the receiver, the type arguments and the other arguments. 
When the result is a functional interface, a closure, lambda or method 
reference argument is checked against it and records it as its parameter type, 
and so does an argument of type `Closure`, for an operator method such as 
`leftShift` too. The static writer converts a closure argument for such a 
parameter to the recorded interface before the cast to the parameter type.
   
   ## Tests
   
   
`ClosuresStaticCompileTest.testClosurePassedForATypeParameterIsConvertedToTheInterfaceTheCallBindsItTo`
 and `MethodReferenceTest.testNotFunctionalInterface3`, which now runs the 
GROOVY-10979 calls and checks the error for a type parameter the call leaves 
unbound, fail without the change. 11,625 tests in the `groovy`, `gls`, `bugs` 
and STC/SC packages pass, and the Checkstyle and CodeNarc gates pass.
   
   Seen in 4.0.33, 5.0.8 and 6.0.0.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to