[ 
https://issues.apache.org/jira/browse/GROOVY-12746?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Paul King resolved GROOVY-12746.
--------------------------------
    Fix Version/s: 7.0.0-alpha-1
         Assignee: Paul King
       Resolution: Fixed

> STC: type closure and lambda parameters for an extension method's functional 
> parameter from the receiver
> --------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12746
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12746
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>             Fix For: 7.0.0-alpha-1
>
>
> When an extension method declares a functional-interface parameter in terms 
> of a type parameter that appears only in its {{self}} parameter, static type 
> checking does not infer that type parameter from the receiver. The closure or 
> lambda parameters fall back to the type parameter's bound, usually {{Object}}.
> {code:groovy}
> @groovy.transform.CompileStatic
> void test() {
>     List<Integer> numbers = [1, 2, 3]
>     numbers.collectParallel { it * 2 }        // Cannot find matching method 
> java.lang.Object#multiply(int)
>     numbers.findAllParallel { it > 1 }        // Cannot find matching method 
> java.lang.Object#compareTo(int)
>     numbers.sumParallel { a, b -> a + b }     // Cannot find matching method 
> java.lang.Object#plus(java.lang.Object)
> }
> {code}
> Every method of {{ParallelCollectionExtensions}} is affected, including the 
> documented {{amounts.sumParallel \{ a, b -> a + b \}}}. So is any extension 
> method, in an extension module or a DGM-like class, whose functional 
> parameter has no {{Closure}} overload with {{@ClosureParams}} to fall back 
> on. Most DGM methods have such an overload, which is why the problem rarely 
> shows.
> The same call written as a static call infers correctly, because the receiver 
> is then an ordinary argument:
> {code:groovy}
> ParallelCollectionExtensions.collectParallel(numbers) { it * 2 }   // OK
> {code}
> h3. Cause
> {{StaticTypeCheckingVisitor.inferClosureParameterTypes}} infers a method's 
> type parameters from explicit type arguments, then from the call's arguments, 
> then falls back to their bounds. For an extension method the receiver is the 
> {{self}} argument, but it is not among the call's arguments, so a type 
> parameter that only {{self}} mentions is never connected to the receiver.
> h3. Fix
> For a non-static extension method, connect the receiver's type to the 
> {{self}} parameter's type after the arguments, so the receiver fills only 
> type parameters that the arguments leave unresolved. Inference that worked 
> before is unchanged. Closures and lambdas that used to be typed with the 
> bound are now typed from the receiver. That matters in two ways:
> * *Errors:* a body that is invalid for the actual element type is now 
> reported with that type, for example {{Integer#toUpperCase()}} for 
> {{List<Integer>}} and {{\{ it.toUpperCase() \}}}, not 
> {{Object#toUpperCase()}}.
> * *Overloads:* a call in the body that passes the parameter to an overloaded 
> method can now select a more specific overload under static compilation, such 
> as {{helper(Integer)}} instead of {{helper(Object)}}. Dynamic Groovy already 
> selects that overload.



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

Reply via email to