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]