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

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

paulk-asert opened a new pull request, #3282:
URL: https://github.com/apache/groovy/pull/3282

   …closure when its call is checked again
   
   A closure with an implicit parameter passed to a method overloaded on 
functional interfaces that take different numbers of parameters, such as 
Function and BinaryOperator, was matched to the interface taking none or one 
parameter (GROOVY-10905) the first time the call was type checked, from the 
parameter count the closure's type carries. Visiting the closure stored its 
inferred type without that count, so when the call was checked again, as the 
body of a loop or closure in which a variable changes type is, or while looking 
for a property after a method was not found on the call's result, the overloads 
were at the same distance and the call was reported as ambiguous. The stored 
type now carries the parameter count too.




> STC: an implicit-parameter closure is reported ambiguous between functional 
> interfaces of different arity when its call is type checked a second time
> -----------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12748
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12748
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Priority: Major
>
> Under {{@TypeChecked}} / {{@CompileStatic}}, a method overloaded on 
> functional interfaces that take different numbers of parameters accepts a 
> closure with an implicit parameter: GROOVY-10905 prefers the interface whose 
> abstract method takes none or one parameter. When the same call is type 
> checked a second time, the preference is lost and the call is reported as 
> ambiguous, although nothing about it has changed.
> {code:groovy}
> import java.util.function.*
> class C {
>     static String m(Function<Integer, Integer> f) { 'function' }
>     static String m(BinaryOperator<Integer> f) { 'binary' }
> }
> @groovy.transform.CompileStatic
> def test() {
>     assert C.m { it } == 'function'   // fine
>     def x = 1
>     for (i in 0..1) {
>         assert C.m { it } == 'function'   // [Static type checking] - 
> Reference to method is ambiguous. Cannot choose between [java.lang.String 
> C#m(java.util.function.Function<java.lang.Integer, java.lang.Integer>), 
> java.lang.String C#m(java.util.function.BinaryOperator<java.lang.Integer>)]
>         x = 'a'
>     }
> }
> test()
> {code}
> Dynamic Groovy chooses {{Function}} in every case.
> h3. When a call is checked again
> * the body of a {{for}} or {{while}} loop, or of a closure, in which a 
> variable changes type, is checked a second time;
> * a method that is not found on the result of the call, e.g. {{C.m \{ it 
> \}.length()}}, makes the type checker check the call again while looking for 
> a property of that name. The expected error (_Cannot find matching method 
> java.lang.Object#length()_) is then accompanied by the misleading ambiguity 
> error.
> h3. Cause
> The first time the call is checked, the closure has not been visited yet, and 
> {{StaticTypeCheckingVisitor.getType}} builds its type with 
> {{CLOSURE_ARGUMENTS}} metadata giving its parameter count (-1 for an implicit 
> parameter), which {{StaticTypeCheckingSupport.getDistance}} uses to prefer 
> the matching interface. Visiting the closure then stores {{Closure<R>}} as 
> its inferred type, without that metadata, and {{getType}} returns the stored 
> type from then on. Without the parameter count, both overloads are at the 
> same distance.
> Closures with declared parameters and method references are not affected on 
> master, as the arity check added by GROOVY-10714 / GROOVY-11010 is recomputed 
> every time; before that, a closure with declared parameters failed in the 
> same way inside a loop.
> h3. Versions
> Seen in 5.1.3 and 6.0.0. 4.0.33 does not have the GROOVY-10905 preference and 
> reports such calls as ambiguous even the first time.
> h3. Fix
> Store the parameter count on the closure's inferred type too, so that it is 
> used however often the call is checked.



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

Reply via email to