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

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


The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
     new fd952456e3 GROOVY-11201: STC: support method pointer to SAM-type 
assignment
fd952456e3 is described below

commit fd952456e33aa3cdd90393af8eebe57815fa6575
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Sun Oct 22 12:49:25 2023 -0500

    GROOVY-11201: STC: support method pointer to SAM-type assignment
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 33 +++++++++----
 src/test/groovy/transform/stc/BugsSTCTest.groovy   | 55 ++++++++++++----------
 2 files changed, 55 insertions(+), 33 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 a1cf015808..1b8b69fb73 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4437,15 +4437,30 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
 
         if (op == EQUAL || op == ELVIS_EQUAL) {
             if (rightRedirect.isDerivedFrom(CLOSURE_TYPE)) {
-                ClosureExpression closureExpression = null;
-                if (rightExpression instanceof ClosureExpression) {
-                    closureExpression = (ClosureExpression) rightExpression;
-                } else if (rightExpression instanceof 
MethodReferenceExpression) {
-                    closureExpression = 
rightExpression.getNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION);
-                }
-                if (closureExpression != null) {
-                    MethodNode abstractMethod = findSAM(left);
-                    if (abstractMethod != null) {
+                MethodNode abstractMethod = findSAM(left);
+                if (abstractMethod != null) {
+                    ClosureExpression closureExpression = null;
+                    if (rightExpression instanceof ClosureExpression) {
+                        closureExpression = (ClosureExpression) 
rightExpression;
+                    } else if (rightExpression instanceof 
MethodPointerExpression) {
+                        closureExpression = 
rightExpression.getNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION);
+                        if (closureExpression == null) { // GROOVY-11201
+                            ClassNode[] paramTypes;
+                            List<MethodNode> methods = 
rightExpression.getNodeMetaData(MethodNode.class);
+                            if (methods == null || methods.isEmpty()) { int 
nParameters = abstractMethod.getParameters().length;
+                                paramTypes = IntStream.range(0, 
nParameters).mapToObj(i -> dynamicType()).toArray(ClassNode[]::new);
+                            } else {
+                                paramTypes = 
collateMethodReferenceParameterTypes((MethodPointerExpression) rightExpression, 
methods.get(0));
+                            }
+                            Parameter[] parameters = new 
Parameter[paramTypes.length];
+                            for (int i = 0; i < paramTypes.length; i += 1) {
+                                parameters[i] = new Parameter(paramTypes[i], 
"p" + i);
+                            }
+                            closureExpression = new 
ClosureExpression(parameters, GENERATED_EMPTY_STATEMENT);
+                            closureExpression.putNodeMetaData(INFERRED_TYPE, 
rightExpression.getNodeMetaData(INFERRED_TYPE));
+                        }
+                    }
+                    if (closureExpression != null) {
                         return inferSAMTypeGenericsInAssignment(left, 
abstractMethod, right, closureExpression);
                     }
                 }
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy 
b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index a50dfde53a..91d339ca84 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -655,29 +655,24 @@ assert o.bar() == 2*o.x
     // GROOVY-6965
     void testShouldNotFailWithClassCastExceptionDuringCompilation() {
         assertScript '''
-interface Job {
-  Runnable getRunnable()
-}
-
-
-class Printer implements Job{
-
-  protected void execute() {
-    println "Printing"
-  }
-
-  public void acceptsRunnable(Runnable r){
-    r.run()
-  }
-
-  public Runnable getRunnable(){
-     acceptsRunnable(this.&execute) // OK
-     return this.&execute           // compile error
-  }
-}
+            interface Job {
+                Runnable getRunnable()
+            }
+            class Printer implements Job {
+                protected void execute() {
+                    println "Printing"
+                }
+                void acceptsRunnable(Runnable r) {
+                    r.run()
+                }
+                Runnable getRunnable() {
+                    acceptsRunnable(this.&execute) // works
+                    return this.&execute           // fails
+                }
+            }
 
-Printer
-'''
+            new Printer().runnable.run()
+        '''
     }
 
     // GROOVY-6970
@@ -968,14 +963,26 @@ Printer
         shouldFailWithMessages '''
             class C { final foo }
             def set = C.&setFoo
-        ''', 'Cannot find matching method C#setFoo'
+        ''',
+        'Cannot find matching method C#setFoo'
     }
 
     // GROOVY-9463
     void testMethodPointerUnknownReference() {
         shouldFailWithMessages '''
             def ptr = String.&toLowerCaseX
-        ''', 'Cannot find matching method java.lang.String#toLowerCaseX.'
+        ''',
+        'Cannot find matching method java.lang.String#toLowerCaseX'
+    }
+
+    // GROOVY-11201
+    void testMethodPointerClosureCoercion() {
+        for (op in ['.&', '::']) {
+            assertScript """import java.util.function.Consumer
+                void setX(String string) { }
+                Consumer<String> c = this${op}setX
+            """
+        }
     }
 
     // GROOVY-9938

Reply via email to