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:45:14 UTC
[groovy] 02/02: 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 GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit abbd5b2937a6f6335297ebc85eeb936b61064da0
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 9310f57b2a..b8d57537df 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -1493,13 +1493,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());
@@ -1509,16 +1520,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 5ac6a3727a..95714c9ee4 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5305,8 +5305,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
}
}
@@ -5632,8 +5633,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 1af2b449a4..ad6a5cc2ea 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -634,6 +634,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> {