[ 
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)

Reply via email to