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 2022/05/16 19:32:26 UTC

[groovy] 03/03: GROOVY-10343: STC: resolve type parameter bounded by a type parameter

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

commit 7f3c77d73cdd90d1cffa12e2281b3e5de7853efa
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon May 16 11:58:56 2022 -0500

    GROOVY-10343: STC: resolve type parameter bounded by a type parameter
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 28 ++++++++++++----------
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 17 +++++++++++++
 2 files changed, 32 insertions(+), 13 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 ebbf3945c2..2fdbb432b0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1606,22 +1606,24 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static ClassNode extractType(final GenericsType gt) {
+    private static ClassNode extractType(GenericsType gt) {
+        ClassNode cn;
         if (!gt.isPlaceholder()) {
-            return gt.getType();
-        }
-        // For a placeholder, a type based on the generics type is used for the compatibility check, to match on
-        // the actual bounds and not the name of the placeholder.
-        ClassNode replacementType = gt.getType().redirect();
-        if (gt.getType().getGenericsTypes() != null) {
-            GenericsType realGt = gt.getType().getGenericsTypes()[0];
-            if (realGt.getLowerBound() != null) {
-                replacementType = realGt.getLowerBound();
-            } else if (realGt.getUpperBounds() != null && realGt.getUpperBounds().length > 0) {
-                replacementType = realGt.getUpperBounds()[0];
+            cn = gt.getType();
+        } else {
+            // discard the placeholder
+            cn = gt.getType().redirect();
+
+            if (gt.getType().getGenericsTypes() != null)
+                gt = gt.getType().getGenericsTypes()[0];
+
+            if (gt.getLowerBound() != null) {
+                cn = gt.getLowerBound();
+            } else if (asBoolean(gt.getUpperBounds())) {
+                cn = gt.getUpperBounds()[0];
             }
         }
-        return replacementType;
+        return cn;
     }
 
     private static boolean equalIncludingGenerics(final GenericsType orig, final GenericsType copy) {
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 2622f7303a..ef74410951 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1219,6 +1219,23 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10343
+    void testDiamondInferrenceFromConstructor27() {
+        assertScript '''
+            class C<T1, T2 extends T1> {
+                T1 p
+                C(T1 p) { this.p = p }
+                T2 m() { return null }
+            }
+            void test(Integer x) {
+                def c = new C<>(x) // type witness for T1 can also help bound T2
+                def y = c.m()
+                Integer z = y // Cannot assign value of type Object to variable of type Integer
+            }
+            test(1234)
+        '''
+    }
+
     // GROOVY-10280
     void testTypeArgumentPropagation() {
         assertScript '''