[
https://issues.apache.org/jira/browse/GROOVY-12616?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18136784#comment-18136784
]
ASF GitHub Bot commented on GROOVY-12616:
-----------------------------------------
paulk-asert commented on PR #3164:
URL: https://github.com/apache/groovy/pull/3164#issuecomment-6588498663
Thanks Daniel, all three points confirmed and addressed.
**Generic method pointers.** `ToIntFunction<Long> f = P.&id`, `new P().&me`,
`use(P.&id)` and also `List.&first` (the type parameter from a class receiver)
are now "Possible loss of precision", as for `::`.
`ReturnConversionConsistencyTest` has a generic method pointer form (`G<T> g =
H.&id`), with the same `int->char` exception as the generic method reference.
I did it slightly differently from attaching `CLOSURE_ARGUMENTS`: the
functional interface's parameter types are used only to resolve the returned
type parameter, not to select among overloads. A method pointer is still a
`Closure` that picks its method at run time, so narrowing the candidates
statically could check a method other than the one called. For example, with
`static int f(Object o)` and `static long f(Long l)`, `ToIntFunction<Object> g
= C.&f` would pass as `f(Object)`, but `g.applyAsInt(5L)` calls `f(Long)` and
narrows its `long` silently. That case stays rejected, and there is a test for
it. `.&` is otherwise unchanged at run time, so `memoize()` and the like still
work under `@CompileStatic`.
**Docs.** The `char` wording now says `char` is not converted to a number
type, and only an `int` or a one-character string constant is converted to
`char`. That is the existing assignment rule, which this PR keeps; its oddities
(no range check for `int`, `Integer` rejected, the overlap with GROOVY-12620)
are in GROOVY-12648. The `Supplier<Byte> s = P::v` case is listed under "Now
rejected": it is the same rule a method's `return` (`Byte m() { P.v() }`)
already applies, and before, `s.get()` returned an `Integer`. The heading no
longer says "primitive".
**The equality test.** I've added a comment saying it has to come before the
erased branch and why.
**`null` unboxing.** I've kept `Boolean`/`Character` type arguments on the
metafactory as you suggested, but split the `null` behaviour into GROOVY-12647.
Probing every form shows the result already varies by form and mode in 6.0.0,
and this PR leaves it as it was:
| Returned `null` to | method `return` | `.&` / closure, any mode | lambda
dyn/TC | lambda CS | `::` dyn/TC | `::` CS |
|---|---|---|---|---|---|---|
| `boolean` (`Boolean`) | false | false | false | false | false | **NPE** |
| `int` (`Integer`) | NPE | GroovyCastException | GroovyCastException | NPE
| GroovyCastException | NPE |
| `char` (`Character`) | NPE | `'\0'` | `'\0'` | NPE | `'\0'` | NPE |
For `boolean`, the `@CompileStatic` method reference is the only form that
throws; even a `@CompileStatic` lambda gives `false`. For `char`, the
closure-based forms give `'\0'` while a method's `return` and the
`@CompileStatic` lambda and method reference throw. Making these agree involves
the closure conversion and the `@CompileStatic` lambda as well as the method
reference adapter, so it seemed better as its own change.
> STC rejects a closure or lambda that returns a primitive needing only a
> widening conversion to the SAM's primitive return type
> ------------------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12616
> URL: https://issues.apache.org/jira/browse/GROOVY-12616
> 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.ToLongFunction
> @groovy.transform.CompileStatic
> class C {
> static void main(args) {
> ToLongFunction<String> f = (String s) -> s.length()
> assert f.applyAsLong('abc') == 3L
> }
> }
> {code}
> Actual: {{[Static type checking] - Cannot return value of type int for lambda
> expecting long}}. The same happens under @TypeChecked, with a closure (passed
> for a ToLongFunction parameter, or a closure returning 42 assigned to a
> LongSupplier), for ToDoubleFunction from int, long or float, for char to int,
> and for Integer to long.
> Expected: compiles and runs, as in Java (JLS 5.2 allows a widening primitive
> conversion, optionally after unboxing, in an assignment context) and as with
> the method reference {{C::len}} or method pointer {{C.&len}}. Narrowing (long
> to int) should still be rejected.
> Cause: {{StaticTypeCheckingVisitor.checkReturnType}} accepts a closure or
> lambda return value only when the wrapper of the SAM return type is
> compatible with the wrapper of the value type, and Long is not compatible
> with Integer.
> Seen in 4.0.33, 5.0.8 and 6.0.0.
> PR: https://github.com/apache/groovy/pull/3142
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)