[
https://issues.apache.org/jira/browse/GROOVY-12748?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18140917#comment-18140917
]
ASF GitHub Bot commented on GROOVY-12748:
-----------------------------------------
testlens-app[bot] commented on PR #3282:
URL: https://github.com/apache/groovy/pull/3282#issuecomment-6732199149
## ✅ All tests passed ✅
🏷️ Commit: 85ed2652af5336638aad0ceb2667328104996b58
▶️ Tests: 130314 executed
⚪️ Checks: 26/26 completed
---
_Learn more about TestLens at
[testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
> 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)