[ 
https://issues.apache.org/jira/browse/GROOVY-12616?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18135639#comment-18135639
 ] 

ASF GitHub Bot commented on GROOVY-12616:
-----------------------------------------

codeconsole opened a new pull request, #3142:
URL: https://github.com/apache/groovy/pull/3142

   Static type checking rejects a closure or lambda whose return value needs a 
widening primitive conversion to the SAM's primitive return type:
   
   ```groovy
   import java.util.function.ToLongFunction
   @groovy.transform.CompileStatic
   class C {
       static void main(args) {
           ToLongFunction<String> f = (String s) -> s.length() // Cannot return 
value of type int for lambda expecting long
           assert f.applyAsLong('abc') == 3L
       }
   }
   ```
   
   Java accepts this, and so do `C::len` and `C.&len`. 4.0.33, 5.0.8 and 6.0.0 
reject it the same way. `StaticTypeCheckingVisitor.checkReturnType` compared 
the wrapped types only, so `int` to `long`, `int`/`long`/`float` to `double`, 
`char` to `int`, and `Integer` to `long` were all reported as incompatible.
   
   `checkReturnType` now accepts a return value whose type, after unboxing, 
widens to the primitive SAM return type under JLS 5.1.2. In that case the SAM 
return type is recorded as the closure's return type, so static compilation 
emits the conversion (`i2l`, `l2d`, ...). These are still rejected:
   - narrowing, for example long to int and char to short;
   - boxing into a different wrapper, for example int for `Supplier<Long>` 
(GROOVY-11414).
   
   ## Tests
   
   `CoercionSTCTest.testCoerceToFunctionalInterface22` covers lambdas and 
closures, assigned, coerced with `as` and passed as method arguments; 
`ToLongFunction`, `ToDoubleFunction`, `LongSupplier`, `DoubleUnaryOperator` and 
`IntSupplier`; char/byte widening, unboxing then widening, an instance-property 
capture and mixed returns; and rejection of long, double and Long returns for 
an int SAM, and of char for a short SAM. It fails without the change both 
type-checked and in `CoercionStaticCompileTests`. `groovy.transform.stc.*` and 
`org.codehaus.groovy.classgen.asm.sc.*` pass. The Checkstyle and CodeNarc gates 
pass.
   




> 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.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to