codeconsole opened a new pull request, #3134:
URL: https://github.com/apache/groovy/pull/3134
Static type checking accepts a method pointer or method reference whose
method returns a type that does not fit the return type of the target
functional interface:
```groovy
import java.util.function.Supplier
@groovy.transform.CompileStatic
class C {
int intMethod() { 1 }
Supplier<String> f() { this.&intMethod }
String take(Supplier<String> s) { s.get() }
def g() { take(this::intMethod) }
def h() { Supplier<String> s = this::intMethod; s.get().toUpperCase() }
// ClassCastException: Integer cannot be cast to String
}
```
4.0.33, 5.0.8 and 6.0.0 fail the same way. The return-type check in
`visitMethodPointerExpression` (GROOVY-10858) used
`checkCompatibleAssignmentTypes`. That accepts String, Boolean and wider number
wrappers from any type, but a method pointer or reference never converts the
value its method returns. So `Supplier<String>` from `int`, `Supplier<Boolean>`
from `String` and `Supplier<Long>` from `int` compiled and failed at run time.
The equivalent lambda is already rejected. Also, a method pointer (`.&`) got no
target type when returned from a method or assigned, so it was not checked at
all.
Now a reference-typed SAM return type must be a supertype of the (boxed)
method return type. Primitive SAM return types (`long` from `int`, `boolean`)
keep the assignment rules. `applyTargetType` gives a method pointer the target
type, as it already did for a method reference and as method-call arguments do.
With several overloads (such as `Math.&abs` as a `Function<Integer,Integer>`),
the reference is accepted if any overload returns a compatible type, instead of
checking only their common supertype.
A `def` or `Object`-returning method used as a `Supplier<String>` is now
rejected too. It was accepted only because a String takes anything by
assignment, and it matches the existing rejection for `Function<X,Integer>`,
the lambda rule and Java.
## Tests
`MethodReferenceTest.testIncompatibleReturnType2` fails without the change.
`testCompatibleReturnType` covers the overloaded, widening and supertype cases
that must stay accepted. Both run under `@TypeChecked` and `@CompileStatic`,
for `::` and `.&`. `groovy.transform.stc.*`,
`org.codehaus.groovy.classgen.asm.sc.*`, `bugs.*` and `gls.*` 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]