Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
-
None
Description
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.:
foo { println 42 } // zero-arg case bar { println 'arg:' + it } // one-arg case
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:
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
Example where 0 and 2-arg variants exist:
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
Example where 0 and 1-arg variants exist:
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
Example where 0, 1 and 2-arg variants exist:
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
Attachments
Issue Links
- relates to
-
GROOVY-11010 Ambiguous method reference when expecting a SAM type
- Open
-
GROOVY-11121 unexpected error when having overloaded methods, one of which receiving an Iterable
- Closed
- links to