codeconsole opened a new pull request, #3149:
URL: https://github.com/apache/groovy/pull/3149
Under `@CompileStatic`, a method reference to a method that returns a type
parameter fails at run time when the functional interface returns a primitive
and the type argument is not that primitive's wrapper:
```groovy
@CompileStatic
class C {
static <T> T id(T t) { t }
static void main(args) {
Predicate<String> p = C::id
assert [p.test(''), p.test('x')] == [false, true] //
ClassCastException: String cannot be cast to Boolean
}
}
```
Dynamic Groovy and `@TypeChecked` give `[false, true]`. 4.0.33, 5.0.8 and
6.0.0 fail the same way. The static compiler sets the instantiated return type
to the SAM's wrapper type (GROOVY-10975), so `LambdaMetafactory` casts the
erased return value to `Boolean`, or to `Number` for numeric return types, and
unboxes it.
`StaticTypesMethodReferenceExpressionWriter` now resolves the type argument:
a method type parameter from the argument types the type checker inferred, or a
class type parameter from the receiver type. When `LambdaMetafactory` cannot
convert that type, the reference goes through the synthetic adapter that the
GString parameter bridge already uses. The adapter returns the primitive type
and converts the value as a statically compiled cast does: Groovy truth for
`boolean`, a Groovy cast for numbers and `char`. A type argument that
`LambdaMetafactory` already converts binds directly as before. Examples are
`Map<String,Boolean>::get` as a `Predicate<String>`, where a missing key still
throws `NullPointerException` as in Java, and `Long` for an `int` return type.
Method references whose return type is not a type parameter are not changed.
This and #3143 (GROOVY-12617, non-generic return types) both extend the
adapter in `StaticTypesMethodReferenceExpressionWriter`; whichever lands second
keeps both predicates (one for a concrete return type, one for a type-parameter
return) and a single early return.
## Tests
`MethodReferenceTest.testPrimitiveSAMFromTypeParameterReturnType` (run with
`@CompileDynamic`, `@TypeChecked` and `@CompileStatic`) and
`testPrimitiveSAMFromTypeParameterReturnTypeSerializable` fail without the
change. `testPrimitiveSAMFromTypeParameterReturnTypeNoConversion` checks that
type arguments `LambdaMetafactory` already converts keep their behaviour. The
`groovy.transform.stc`, `org.codehaus.groovy.classgen.asm.sc` and `groovy.bugs`
tests pass. The Checkstyle and CodeNarc gates pass.
--
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]