[
https://issues.apache.org/jira/browse/GROOVY-12588?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18135457#comment-18135457
]
ASF GitHub Bot commented on GROOVY-12588:
-----------------------------------------
codeconsole opened a new pull request, #3113:
URL: https://github.com/apache/groovy/pull/3113
Static type checking rejects a value whose static type is `Closure<R>` (not
a closure literal) when it is assigned to a parameterized functional interface:
```groovy
import java.util.function.Supplier
@groovy.transform.CompileStatic
def m() {
Closure<String> c = { 'a' }
Supplier<String> s = c // Incompatible generic argument types. Cannot
assign groovy.lang.Closure<java.lang.String> to:
java.util.function.Supplier<java.lang.String>
s.get()
}
```
Raw `Supplier s = c` and closure literals are accepted, and dynamic Groovy
coerces the closure. The same error came from properties, subscripts,
ternaries, field assignments and generic methods whose result is a
`Closure<R>`, and for SAM types with parameters (`Function<Integer,String>`,
`Comparator<String>`, ...).
`checkCompatibleAssignmentTypes` already accepts Closure to SAM coercion;
the generics check that runs after it (`checkTypeGenerics`) compared
`Closure<String>` with `Supplier<String>` as a plain parameterized subtype and
failed. It now accepts a `Closure<R>` (or a Closure subclass) when the SAM
type's abstract method, parameterized by the target type, returns void or a
type that accepts `R`, using the same test as the return check for closure
literals. A mismatch such as `Closure<Integer>` to `Supplier<String>` is still
reported. Static compilation emits the same coercion as for the raw case, so
the value is converted to the interface.
## Tests
`CoercionSTCTest.testCoerceToFunctionalInterface22` and
`testCoerceToFunctionalInterface23` fail without the change, both in
`CoercionSTCTest` and in `CoercionStaticCompileTests`;
`testCoerceToFunctionalInterface24` covers the assignments that must stay
errors. `groovy.transform.stc.*`, `org.codehaus.groovy.classgen.asm.sc.*`,
`groovy.bugs.*` and `gls.*` pass. The Checkstyle and CodeNarc gates pass.
Seen in 4.0.33, 5.0.8 and 6.0.0.
> STC rejects a Closure<R> value assigned to a parameterized functional
> interface ("Incompatible generic argument types")
> -----------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12588
> URL: https://issues.apache.org/jira/browse/GROOVY-12588
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 4.0.33, 5.0.8, 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> {code:groovy}
> import java.util.function.Supplier
> @groovy.transform.TypeChecked // or @CompileStatic
> def m() {
> Closure<String> c = { 'a' }
> Supplier<String> s = c
> s.get()
> }
> assert m() == 'a'
> {code}
> Actual result:
> {noformat}
> [Static type checking] - Incompatible generic argument types. Cannot assign
> groovy.lang.Closure<java.lang.String> to:
> java.util.function.Supplier<java.lang.String>
> {noformat}
> Expected result: the script compiles and the closure is coerced to the
> interface, as it is for a closure literal, for a raw target ({{Supplier s =
> c}}) and in dynamic Groovy.
> The same error is reported when the value comes from a property, a subscript,
> a field assignment or a generic method returning a Closure, and for SAM types
> with parameters such as {{Function<Integer,String>}}. The assignment check
> accepts Closure to SAM coercion, but the generics check that follows it
> compares {{Closure<String>}} with {{Supplier<String>}} as if Closure had to
> implement the interface.
> Seen in 4.0.33, 5.0.8, 6.0.0 and master.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)