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

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

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

   Static type checking rejected a closure or lambda that returns an int 
constant for a byte, short or char SAM return type:
   
   ```groovy
   interface S { short get() }
   interface B { byte get() }
   @groovy.transform.CompileStatic
   void test() {
       S s = () -> 1          // Cannot return value of type int for lambda 
expecting short
       B b = { -> 2 }         // Cannot return value of type int for closure 
expecting byte
       assert s.get() == (short) 1 && b.get() == (byte) 2
   }
   ```
   
   Java accepts this. A lambda result expression is in an assignment context, 
and JLS 5.2 allows narrowing an int constant that fits the target type there. 
Groovy already accepts `short x = 1` and `short m() { 1 }`. 4.0.33, 5.0.8 and 
6.0.0 reject it the same way.
   
   `StaticTypeCheckingVisitor.checkReturnType` now accepts a return expression 
that is an int `ConstantExpression` whose value fits the expected primitive 
byte, short or char type. A constant that does not fit (`() -> 70000` for 
short, `{ -> -1 }` for char) and a non-constant int are still rejected. Static 
compilation already converts the value: a lambda body compiles to `iconst_1; 
i2s; ireturn`, and a closure casts the value to the boxed return type.
   
   This and #3142 (GROOVY-12616, widening) each add an `else if` after the 
covariance branch of `checkReturnType` and a helper before `isClosureWithType`; 
whichever lands second keeps both. No case matches both branches.
   
   ## Tests
   
   `CoercionSTCTest.testCoerceNarrowingConstantReturnToFunctionalInterface` 
fails without the change, under both `CoercionSTCTest` and 
`CoercionStaticCompileTests`. It covers closures and lambdas for byte, short 
and char, boundary and negative values, block lambdas with several returns, 
method arguments, `as` coercion, static and instance contexts, and the cases 
that must stay rejected. `groovy.transform.stc.*`, 
`org.codehaus.groovy.classgen.asm.sc.*`, `gls.*` and `groovy.bugs.*` pass. The 
Checkstyle and CodeNarc gates pass.
   




> STC rejects a closure or lambda returning an int constant for a byte, short 
> or char SAM return type
> ---------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12620
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12620
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 4.0.33, 5.0.8, 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> {code:groovy}
> interface S { short get() }
> interface B { byte get() }
> interface C { char get() }
> @groovy.transform.TypeChecked // or @CompileStatic
> void test() {
>     S s = () -> 1
>     B b = { -> 2 }
>     C c = () -> 65
>     assert s.get() == (short) 1 && b.get() == (byte) 2 && c.get() == (char) 65
> }
> test()
> {code}
> Actual:
> {noformat}
> [Static type checking] - Cannot return value of type int for lambda expecting 
> short
> [Static type checking] - Cannot return value of type int for closure 
> expecting byte
> [Static type checking] - Cannot return value of type int for lambda expecting 
> char
> {noformat}
> Expected: the script compiles and runs. Java accepts these lambdas, because 
> JLS 5.2 allows narrowing an int constant that fits the target type in an 
> assignment context, and a lambda result expression is in an assignment 
> context. Groovy already accepts a short variable or a short method return 
> initialised from such a constant, and dynamic Groovy runs the script. A 
> constant that does not fit, such as 70000 for short, or a non-constant int 
> must still be rejected.
> The closure/lambda return check in StaticTypeCheckingVisitor.checkReturnType 
> accepts only a return type that is compatible after wrapping, so int is never 
> accepted where byte, short or char is expected.
> 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