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/15 16:25:30 UTC

[groovy] branch master updated: GROOVY-10622: STC: type parameter with parameterized bound

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

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


The following commit(s) were added to refs/heads/master by this push:
     new a585ab3079 GROOVY-10622: STC: type parameter with parameterized bound
a585ab3079 is described below

commit a585ab3079640e1c11e5117ca292b1624f8298a5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun May 15 11:12:24 2022 -0500

    GROOVY-10622: STC: type parameter with parameterized bound
---
 .../codehaus/groovy/control/ResolveVisitor.java    | 31 +++++++++++---------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 12 +++++---
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 33 ++++++++++++++++++++++
 3 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 20a46b5a15..c71fba8140 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -1494,13 +1494,24 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
         if (genericsType.isResolved()) return true;
         currentClass.setUsingGenerics(true);
         ClassNode type = genericsType.getType();
-        // save name before redirect
-        GenericsTypeName name = new GenericsTypeName(type.getName());
-        visitTypeAnnotations(type);
-        ClassNode[] bounds = genericsType.getUpperBounds();
-        if (!genericParameterNames.containsKey(name)) {
-            if (bounds != null) {
-                for (ClassNode upperBound : bounds) {
+        visitTypeAnnotations(type); // JSR-308 support
+        GenericsType tp = genericParameterNames.get(new GenericsTypeName(type.getName()));
+        if (tp != null) {
+            ClassNode[] bounds = tp.getUpperBounds();
+            if (bounds != null && (bounds.length > 1 || (bounds[0].isRedirectNode()
+                                   && bounds[0].redirect().getGenericsTypes() != null))) {
+                // GROOVY-10622: bounds are too complex for a redirect-only representation
+                //genericsType.setUpperBounds(bounds);
+                type.setGenericsPlaceHolder(true);
+                type.setRedirect(bounds[0]);
+            } else {
+                type.setRedirect(tp.getType());
+            }
+            genericsType.setPlaceholder(true);
+        } else {
+            ClassNode[] upperBounds = genericsType.getUpperBounds();
+            if (upperBounds != null) {
+                for (ClassNode upperBound : upperBounds) {
                     resolveOrFail(upperBound, genericsType);
                     type.setRedirect(upperBound);
                     resolveGenericsTypes(upperBound.getGenericsTypes());
@@ -1510,16 +1521,10 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
             } else {
                 resolveOrFail(type, genericsType);
             }
-        } else {
-            GenericsType gt = genericParameterNames.get(name);
-            type.setRedirect(gt.getType());
-            genericsType.setPlaceholder(true);
         }
-
         if (genericsType.getLowerBound() != null) {
             resolveOrFail(genericsType.getLowerBound(), genericsType);
         }
-
         if (resolveGenericsTypes(type.getGenericsTypes())) {
             genericsType.setResolved(genericsType.getType().isResolved());
         }
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 e4bfc5557c..aa97772762 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5313,8 +5313,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (context != null) {
             returnType = applyGenericsContext(context, returnType);
 
-            if (receiver.getGenericsTypes() == null && receiver.redirect().getGenericsTypes() != null && GenericsUtils.hasUnresolvedGenerics(returnType)) {
-                returnType = returnType.getPlainNodeReference(); // GROOVY-10049: do not return "Stream<E>" for raw type "List#stream()"
+            if (receiver.getGenericsTypes() == null && receiver.redirect().getGenericsTypes() != null
+                    && !receiver.isGenericsPlaceHolder() && GenericsUtils.hasUnresolvedGenerics(returnType)) {
+                returnType = returnType.getPlainNodeReference(); // GROOVY-10049: not "Stream<E>" for raw type
             }
         }
 
@@ -5640,8 +5641,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             ClassNode current = type;
             while (current != null) {
                 Map<GenericsTypeName, GenericsType> placeHolders = new HashMap<>();
-                // GROOVY-10055: handle diamond or raw
-                if (current.getGenericsTypes() != null
+                if (current.isGenericsPlaceHolder())
+                    // GROOVY-10622: type param bound "T extends Set<Type>"
+                    current = current.asGenericsType().getUpperBounds()[0];
+                // GROOVY-10055: handle diamond or raw type
+                else if (current.getGenericsTypes() != null
                         ? current.getGenericsTypes().length == 0
                         : current.redirect().getGenericsTypes() != null) {
                     for (GenericsType gt : current.redirect().getGenericsTypes()) {
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 8dc1cff70a..2c03f99429 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -662,6 +662,39 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10622
+    void testReturnTypeInferenceWithMethodGenerics26() {
+        String types = '''
+            @groovy.transform.TupleConstructor(defaults=false)
+            class A<X> {
+                X x
+            }
+            @groovy.transform.TupleConstructor(defaults=false)
+            class B<Y> {
+                Y y
+            }
+            class C {
+                C(byte b) { }
+            }
+        '''
+        assertScript types + '''
+            def <T extends A<Byte>> void test(B<T> b_of_t) {
+                def t = b_of_t.getY()
+                def x = t.getX()
+                new C(x)
+            }
+            test(new B<>(new A<>((byte)1)))
+        '''
+        assertScript types + '''
+            def <T extends A<Byte>> void test(B<T> b_of_t) {
+                def t = b_of_t.y
+                def x = t.x
+                new C(x)
+            }
+            test(new B<>(new A<>((byte)1)))
+        '''
+    }
+
     void testDiamondInferrenceFromConstructor1() {
         assertScript '''
             class Foo<U> {