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

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

codeconsole commented on PR #3089:
URL: https://github.com/apache/groovy/pull/3089#issuecomment-6526950796

   @daniellansun
   
   1. Merged current `master` into the branch (7bee983391), which includes 
#3094 / GROOVY-12565, so the coverage job now runs with the 
`CopyOnWriteArrayList` fix.
   
   2. When every argument for `T` is a closure, none of them is a witness, so 
for an unbounded `<T>` the call binds `T` to no interface and the closures are 
passed as they are, as in dynamic Groovy; return type inference is unchanged 
(`T` is `Closure`). When the bound of `T` is a functional interface, the 
declared parameter is already a SAM, the closures stay witnesses and the 
erasure cast converts them, as before. An explicit type argument 
(`C.<Supplier<String>>pick({ 'a' }, { 'b' })`) still binds `T`. 
`ClosuresSTCTest.testClosuresPassedForTheSameTypeParameter` covers `<T> void 
both(T, T)`, `<T> T pick(T, T)` and `<T extends Function<String, String>> T 
second(T, T)` with two closures, under `@TypeChecked` and `@CompileStatic` 
(ca144e6318).
   
      Checking nested inference found a bug: `list.add(pick({ 'a' }, { 'b' }))` 
on a `List<Supplier<String>>` stored the closure. The type checker recorded 
`Supplier`, but `StaticInvocationWriter.visitArgument` took the argument type 
from the operand stack, where the call of `pick` leaves `Object`. It now takes 
the type checker's type, as the variadic path already did (f6f55157f6). 
`ClosuresStaticCompileTest.testClosureReturnedForATypeParameterIsConvertedToTheInterfaceTheCallBindsItTo`
 covers `add`, `<<`, `Collections.addAll` and `Map.put`, and fails without the 
change.
   
   3. No. `getFunctionalTypeArgument` requires `isCompatibleWith(type, 
parameterType.redirect())`, the same check `OperandStack.doConvertAndCast` 
makes before it emits anything, so after the first cast the operand is the SAM 
and the cast to the parameter type emits nothing. The placeholder's redirect is 
its first bound, which is also the JVM erasure, so the descriptor matches. 
`ClosuresStaticCompileTest.testClosurePassedForATypeParameterWithSeveralBounds` 
passes a closure for `<T extends Runnable & Serializable>` bound to a 
`SerializableRunnable` subinterface (converted, verifies and runs) and for `<T 
extends Comparable<T>>` (converted to `Comparable` by the erasure cast, as 
before) (ca144e6318).
   
   4. Either order. The only textual conflict was that both PRs appended a test 
at the end of `ClosuresStaticCompileTest`; #3090 now adds its test earlier in 
the file, and `git merge-tree` merges the two branches cleanly both ways, to 
the same tree. Neither depends on the other's tests: on a merge of both, the 
`groovy.transform.stc` and `org.codehaus.groovy.classgen.asm.sc` packages pass. 
The STC metadata is on different nodes: #3090 records PARAMETER_TYPE on a named 
constructor argument's key, this PR on call arguments; and #3090 turns a 
closure assigned to a property into a cast before the setter call is written, 
so this PR's writer sees an argument of the interface type and does not convert 
it again.
   
   The `groovy.transform.stc` and `org.codehaus.groovy.classgen.asm.sc` 
packages pass (4,552 tests), as do the Checkstyle and CodeNarc gates.
   




> 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