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 2023/03/18 17:17:18 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-10270: STC: SAM-type (placeholder) accepts closure

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 46db2baa70 GROOVY-10270: STC: SAM-type (placeholder) accepts closure
46db2baa70 is described below

commit 46db2baa707efca10ec46e4f0d5fc2f0ae3e47cd
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Mar 18 11:05:12 2023 -0500

    GROOVY-10270: STC: SAM-type (placeholder) accepts closure
    
    3_0_X backport
---
 .../transform/stc/StaticTypeCheckingSupport.java      | 19 ++++++++++++++-----
 src/test/groovy/transform/stc/GenericsSTCTest.groovy  | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index a1373bd179..41ba4c74bf 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -89,6 +89,7 @@ import static org.codehaus.groovy.ast.ClassHelper.GSTRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Integer_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Long_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Number_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.OBJECT;
 import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Short_TYPE;
@@ -1559,22 +1560,30 @@ public abstract class StaticTypeCheckingSupport {
 
     private static boolean compatibleConnection(final GenericsType resolved, final GenericsType connection) {
         if (resolved.isPlaceholder()
-                && resolved.getUpperBounds() != null
-                && resolved.getUpperBounds().length == 1
+                &&  resolved.getUpperBounds() != null
+                &&  resolved.getUpperBounds().length == 1
                 && !resolved.getUpperBounds()[0].isGenericsPlaceHolder()
-                && resolved.getUpperBounds()[0].getName().equals("java.lang.Object")) {
+                &&  resolved.getUpperBounds()[0].getName().equals(OBJECT)) {
             return true;
         }
         ClassNode compareNode;
         if (hasNonTrivialBounds(resolved)) {
             compareNode = getCombinedBoundType(resolved);
-            compareNode = compareNode.redirect().getPlainNodeReference();
+            compareNode = compareNode.getPlainNodeReference();
         } else if (!resolved.isPlaceholder()) {
             compareNode = resolved.getType().getPlainNodeReference();
         } else {
             return true;
         }
-        GenericsType gt = connection.isWildcard() ? connection : buildWildcardType(connection);
+
+        GenericsType gt;
+        if (connection.isWildcard()) {
+            gt = connection;
+        } else if (!connection.isPlaceholder() && connection.getType().equals(CLOSURE_TYPE) && isSAMType(compareNode)) {
+            return true; // GROOVY-10270: SAM-type (placeholder) accepts closure
+        } else {
+            gt = buildWildcardType(connection);
+        }
         return gt.isCompatibleWith(compareNode);
     }
 
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index ed7e094a27..598120a2b1 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -3412,6 +3412,24 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         }
     }
 
+    // GROOVY-10270
+    void testCompatibleArgumentsForPlaceholders12() {
+        assertScript '''import java.util.function.*
+            void a(Function<Number,Byte> fn) { }
+            class B {
+                B(Function<Number,Byte> fn) { }
+            }
+            class C<T> {
+                C(T t) { }
+            }
+
+            a({ Number x -> x.byteValue() })
+            new B({ Number x -> x.byteValue() })
+            new C<Function<Number,Byte>>({ Number x -> x.byteValue() } as Function<Number,Byte>)
+            new C<Function<Number,Byte>>({ Number x -> x.byteValue() }                         )
+        '''
+    }
+
     void testIncompatibleArgumentsForPlaceholders1() {
         shouldFailWithMessages '''
             def <T extends Number> T test(T one, T two) { }