You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2024/01/04 20:34:41 UTC

(groovy) branch GROOVY_3_0_X updated: GROOVY-11241: STC: first param is implicit receiver

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 96f62e3068 GROOVY-11241: STC: first param is implicit receiver
96f62e3068 is described below

commit 96f62e3068cdacf5d7f5df10632fed48240e3dd8
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jan 4 14:20:27 2024 -0600

    GROOVY-11241: STC: first param is implicit receiver
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  8 ++++
 .../transform/stc/MethodReferenceTest.groovy       | 51 +++++++++++++++++++++-
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 447daa360a..9cf9c36b86 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5682,14 +5682,22 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (mn != null) {
                     ClassNode[] pTypes = collateMethodReferenceParameterTypes(mp, mn);
                     Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
+                    // GROOVY-11241: implicit receiver for "Optional::get" is resolved now
+                    if (!mn.isStatic() && mp.getExpression() instanceof ClassExpression) {
+                        ClassNode objectType = parameters[0].getType();
+                        objectType = applyGenericsContext(placeholders, objectType);
+                        extractGenericsConnections(connections, objectType, pTypes[0].redirect());
+                    }
                     for (int i = 0, n = parameters.length; i < n; i += 1) {
                         // SAM parameters should align one-for-one with the referenced method's parameters
                         extractGenericsConnections(connections, parameters[i].getOriginType(), pTypes[i]);
                     }
                     // convert the method reference's generics into the SAM's generics domain
                     closureReturnType = applyGenericsContext(connections, closureReturnType);
+                    pTypes = applyGenericsContext(connections, pTypes);
                     // apply known generics connections to the placeholders of the return type
                     closureReturnType = applyGenericsContext(placeholders, closureReturnType);
+                    pTypes = applyGenericsContext(placeholders, pTypes); // and the parameters
 
                     expression = new ClosureExpression(Arrays.stream(pTypes).map(t -> new Parameter(t,"")).toArray(Parameter[]::new), null);
                 }
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index a35738ec23..f80c7c8be9 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -237,8 +237,35 @@ final class MethodReferenceTest {
         '''
     }
 
-    @Test // class::instanceMethod -- GROOVY-11241
+    @Test // class::instanceMethod -- GROOVY-9803
     void testFunctionCI9() {
+        assertScript imports + '''
+            class Try<X> { X x
+                static <Y> Try<Y> success(Y y) {
+                    new Try<Y>(x: y)
+                }
+                def <Z> Try<Z> map(Function<? super X, ? extends Z> f) {
+                    new Try<Z>(x: f.apply(x))
+                }
+            }
+
+            static <E> Set<E> asSet(E element) {
+                Collections.singleton(element)
+            }
+
+            @CompileStatic
+            Try<String> test() {
+                def try_of_str = Try.success('WORKS')
+                def try_of_opt = try_of_str.map(this::asSet)
+                    try_of_str = try_of_opt.map{it.first().toLowerCase()}
+            }
+
+            assert test().x == 'works'
+        '''
+    }
+
+    @Test // class::instanceMethod -- GROOVY-11241
+    void testFunctionCI10() {
         assertScript imports + '''
             @Grab('io.vavr:vavr:0.10.4')
             import io.vavr.control.*
@@ -254,6 +281,26 @@ final class MethodReferenceTest {
             assert test().get() == 42
         '''
 
+        assertScript imports + '''
+            class Try<X> { X x
+                static <Y> Try<Y> of(Supplier<? extends Y> s) {
+                    new Try<Y>(x: s.get())
+                }
+                def <Z> Try<Z> mapTry(Function<? super X, ? extends Z> f) {
+                    new Try<Z>(x: f.apply(x))
+                }
+            }
+
+            @CompileStatic
+            Try<String> test() {
+                def try_of = Try.of{Optional.of('works')}
+                def result = try_of.mapTry(Optional.&get) // Function<T,_> and Optional<T>
+                return result
+            }
+
+            assert test().x == 'works'
+        '''
+
         assertScript imports + '''
             @Grab('io.vavr:vavr:0.10.4')
             import io.vavr.control.Try
@@ -280,7 +327,7 @@ final class MethodReferenceTest {
     }
 
     @Test // class::instanceMethod -- GROOVY-11259
-    void testFunctionCI10() {
+    void testFunctionCI11() {
         assertScript imports + '''
             def consume(Set<String> keys){keys}
             @CompileStatic