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

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

codeconsole opened a new pull request, #3089:
URL: https://github.com/apache/groovy/pull/3089

   Under `@CompileStatic`, a closure passed for a parameter declared with a 
type parameter was passed unconverted when the call binds the type parameter to 
a functional interface. The type checker accepted the call, but the writer cast 
the argument to the erasure of the parameter type, so the closure itself was 
stored and a later call of the interface method failed:
   
   ```groovy
   @CompileStatic
   String f() {
       List<Supplier<String>> list = []
       list.add { 'x' }
       list[0].get() // ClassCastException: _f_closure1 cannot be cast to 
java.util.function.Supplier
   }
   ```
   
   The same held for `map.put('k') { ... }` on a `Map<String, Function<String, 
String>>`, `set`, `putIfAbsent`, `AtomicReference.set`, a constructor argument 
of a parameterized type, `list << { ... }`, the varargs of 
`Collections.addAll`, and a variable or conditional expression of type 
`Closure`. For `<T extends Function<String, String>> T second(T a, T b)` called 
with a `Shout` (a subinterface of `Function`) and a closure, the closure became 
a `Function` and the cast of the result to `Shout` failed. The type checker 
also did not take the parameter for a functional interface: it inferred no 
parameter types for the closure (`it.toUpperCase()` was rejected), compiled a 
lambda for it as a closure, and rejected a method reference with "parameter 
type 'E' is not a functional interface", which is GROOVY-10979.
   
   The type checker now resolves such a parameter type for the call, as it does 
the return type, from the receiver, the type arguments and the other arguments. 
When the result is a functional interface, a closure, lambda or method 
reference argument is checked against it and records it as its parameter type, 
and so does an argument of type `Closure`, for an operator method such as 
`leftShift` too. The static writer converts a closure argument for such a 
parameter to the recorded interface before the cast to the parameter type.
   
   ## Tests
   
   
`ClosuresStaticCompileTest.testClosurePassedForATypeParameterIsConvertedToTheInterfaceTheCallBindsItTo`
 and `MethodReferenceTest.testNotFunctionalInterface3`, which now runs the 
GROOVY-10979 calls and checks the error for a type parameter the call leaves 
unbound, fail without the change. 11,625 tests in the `groovy`, `gls`, `bugs` 
and STC/SC packages pass, and the Checkstyle and CodeNarc gates pass.
   
   Seen in 4.0.33, 5.0.8 and 6.0.0.
   




> Cannot provide method reference to a type parameter instantiated with a SAM 
> type
> --------------------------------------------------------------------------------
>
>                 Key: GROOVY-10979
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10979
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static Type Checker
>            Reporter: Thodoris Sotiropoulos
>            Priority: Minor
>
> I have the following program
> {code}
> import java.util.function.*;
> import java.util.stream.*;
> public class Test {
>     public static void test() {
>       Stream<Number> x = null;
>       BiFunction<Function<String, Integer>, Number, Function<String, 
> Integer>> y = null;
>       BinaryOperator<Function<String, Integer>> z = null;
>       x.<Function<String, Integer>>reduce(Test::m, y, z);  // fails
>       x.reduce(Test::m, y, z);   // fails
>       x.reduce((d) -> 1, y, z);   // works
>     }
>     public static Integer m(String x) { return 1; }
> }
> {code}
> h3. Actual behavior
> {code}
> org.codehaus.groovy.control.MultipleCompilationErrorsException: startup 
> failed:
> test.groovy: 12: The argument is a method reference, but the parameter type 
> is not a functional interface
>  @ line 12, column 43.
>    ction<String, Integer>>reduce(Test::m, y
>                                  ^
> test.groovy: 13: The argument is a method reference, but the parameter type 
> is not a functional interface
>  @ line 13, column 16.
>          x.reduce(Test::m, y, z);   // fails
>                   ^
> 2 errors
> {code}
> h3. Expected behavior
> Compile successfully
> Tested against master (commit: 55c6edfd81a64ce759357a3976070c0811bff637)



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

Reply via email to