You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "ASF GitHub Bot (Jira)" <ji...@apache.org> on 2023/01/17 22:31:00 UTC

[jira] [Commented] (GROOVY-10905) Improve matching implicit arg closures to SAM types

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

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

paulk-asert merged PR #1846:
URL: https://github.com/apache/groovy/pull/1846




> Improve matching implicit arg closures to SAM types
> ---------------------------------------------------
>
>                 Key: GROOVY-10905
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10905
>             Project: Groovy
>          Issue Type: Improvement
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>             Fix For: 5.x
>
>
> When matching Closures to SAM types, we have special treatment for Closures without a formal parameter section. Such Closures may have 0 or 1 arguments, e.g.:
> {code}
> foo { println 42 } // zero-arg case
> bar { println 'arg:' + it } // one-arg case
> {code}
> Our current matching says that because of this ambiguity, we know nothing about the number of parameters, but this assumption is throwing away information: the fact that we are expecting 0 or 1 args. I'd like to propose for Groovy 5 that we match 0 or 1-arg SAMs more closely that say a 2-arg SAM for such a Closure.
> The impact of this is that there will be less ambiguity errors (or conversely, less places where we need to cast to get the correct method). It obviously doesn't help if there are both 0 and 1-arg options available, where casting would still be required.
> Example where 1 and 2-arg variants exist:
> {code}
> def method1(IntUnaryOperator unary) { '1a' }
> def method1(IntBinaryOperator binary) { '1b' }
> // unchanged behavior
> assert method1{ x -> } == '1a'    // explicit 1 arg
> assert method1{ x, y -> } == '1b'    // explicit 2 args
> assert method1({ } as IntUnaryOperator) == '1a'    // explicit cast for implicit arg
> assert method1({ } as IntBinaryOperator) == '1b'    // explicit cast for implicit arg
> // "method1{ -> }" would remain ambiguous
> // proposed change: implicit arg will match Unary over Binary since Unary is the only match for 0 or 1 args
> assert method1{ } == '1a' // currently fails with Ambiguous method overloading
> {code}
> Example where 0 and 2-arg variants exist:
> {code}
> def method2(IntSupplier supplier) { '2a' }
> def method2(IntBinaryOperator binary) { '2b' }
> // unchanged behavior
> assert method2{ -> } == '2a'
> assert method2{ x, y -> } == '2b'
> assert method2({ } as IntSupplier) == '2a'
> assert method2({ } as IntBinaryOperator) == '2b'
> // "method2{ a -> }" would remain Ambiguous
> // proposed change: implicit arg will match Supplier over Binary since Unary is the only match for 0 or 1 args
> assert method2{} == '2a' // currently fails with Ambiguous method overloading
> {code}
> Example where 0 and 1-arg variants exist:
> {code}
> def method3(IntSupplier supplier) { '3a' }
> def method3(IntUnaryOperator unary) { '3b' }
> assert method3{ -> } == '3a'
> assert method3{ x -> } == '3b'
> assert method3({ } as IntSupplier) == '3a'
> assert method3({ } as IntUnaryOperator) == '3b'
> // "method3{ }" will remain Ambiguous since "0 or 1" matches both; error message is unchanged
> {code}
> Example where 0, 1 and 2-arg variants exist:
> {code}
> def method4(IntSupplier supplier) { '4a' }
> def method4(IntUnaryOperator unary) { '4b' }
> def method4(IntBinaryOperator binary) { '4c'  }
> assert method4{ -> } == '4a'
> assert method4{ x -> } == '4b'
> assert method4{ x, y -> } == '4c'
> assert method4({ } as IntSupplier) == '4a'
> assert method4({ } as IntUnaryOperator) == '4b'
> assert method4({ } as IntBinaryOperator) == '4c'
> // "method4{ }" will remain Ambiguous but error message will change from:
> //    Ambiguous method overloading [...] due to overlapping prototypes between:
> //    [interface java.util.function.IntBinaryOperator]
> //    [interface java.util.function.IntSupplier]
> //    [interface java.util.function.IntUnaryOperator]
> // to:
> //    Ambiguous method overloading [...] due to overlapping prototypes between:
> //    [interface java.util.function.IntSupplier]
> //    [interface java.util.function.IntUnaryOperator]
> // Since 0 or 1 variants will match closer than higher parameter numbers
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)