You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2021/04/23 14:32:00 UTC

[jira] [Commented] (GROOVY-10052) STC sometimes requires explicit closure to SAM cast inside of another closure

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

Eric Milles commented on GROOVY-10052:
--------------------------------------

There is a check in {{StaticTypeCheckingVisitor#visitClosureExpression}} that triggers a second visitation for the closure-nested example:
{code:java}
        boolean typeChanged = isSecondPassNeededForControlStructure(variableTypes, oldTracker);
        if (typeChanged) visitClosureExpression(expression);
{code}

> STC sometimes requires explicit closure to SAM cast inside of another closure
> -----------------------------------------------------------------------------
>
>                 Key: GROOVY-10052
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10052
>             Project: Groovy
>          Issue Type: Improvement
>          Components: Static compilation, Static Type Checker
>    Affects Versions: 3.0.8
>            Reporter: Damir Murat
>            Assignee: Eric Milles
>            Priority: Major
>
> After upgrading to the 3.0.8 version, I observed several improvements in STC, but it looks like some cases are still uncovered. Say I have the following script (tested with Groovy console):
> {code:java}
> import groovy.transform.CompileStatic
> import java.util.function.Predicate
> import java.util.function.Supplier
> import java.util.stream.Collectors
> @CompileStatic
> class Test {
>   void testMe() {
>     String maybeSomeString = Optional.of("Some Name")
>         .orElseThrow({ new NoSuchElementException("Nothing found") }) // line 1 - no explicit cast
>     println maybeSomeString
>     
>     List stringList = ["1ab", "2cd"]
>         .stream()
>         .flatMap({ it.toList().stream() })
>         .filter({ Character.isLetterOrDigit(it.chars[0]) }) // line 2 - no explicit cast
>         .collect(Collectors.toList())
>     
>     println stringList
>     [1, 2, 3]
>         .stream()
>         .map({
>           String maybeSomeOtherString = Optional
>               .of("Some Other Name")
>               .orElseThrow({ new NoSuchElementException("Nothing found") } as Supplier) // line 3 - explicit cast needed
>           return "$it: $maybeSomeOtherString".toString()
>         })
>         .peek({
>           List list = it.toList()
>               .stream()
>               .filter({ Character.isLetterOrDigit(it.chars[0]) }) // line 4 - no explicit cast and no explicit parameter type
>               .collect(Collectors.toList())
>           println list
>         })
>         .forEach({println it })
>   }
> }
> new Test().testMe()
> {code}
> In line 3, an explicit cast to Supplier is needed. It wasn't required for 3.0.7. When removed, the checker throws
> {code}
> [Static type checking] - Cannot call <X extends java.lang.Throwable> java.util.Optional <java.lang.String>#orElseThrow(java.util.function.Supplier <? extends X>) with arguments [groovy.lang.Closure <java.util.NoSuchElementException>] 
>  at line: 26, column: 41
> {code}
> As can be seen from the sample, coercion works if the closure is not nested inside of another closure.
> For comparison, with the 3.0.7 version, line 1 and 2 behaves the same as for 3.0.8.
> In 3.0.7, line 3 did not require an explicit cast. In line 4, 3.0.7 requires explicit cast and explicit parameter declaration, while 3.0.8 does not require either.
> Tnx



--
This message was sent by Atlassian Jira
(v8.3.4#803005)