You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2022/06/26 14:39:38 UTC
[groovy] branch GROOVY_4_0_X updated: GROOVY-10153: resolve implicit wildcard bounding once type resolved
This is an automated email from the ASF dual-hosted git repository.
sunlan 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 e33edbe99d GROOVY-10153: resolve implicit wildcard bounding once type resolved
e33edbe99d is described below
commit e33edbe99d28212640168ed352cf9c6c035c1b43
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jun 23 15:27:33 2022 -0500
GROOVY-10153: resolve implicit wildcard bounding once type resolved
(cherry picked from commit 06dd5052edc621278cbc1114ffa593baaa3dc7b4)
---
.../codehaus/groovy/control/ResolveVisitor.java | 57 +++++++++++++++-------
.../groovy/transform/stc/GenericsSTCTest.groovy | 15 ++++++
2 files changed, 55 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 b8d57537df..79e7c4fbec 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -378,8 +378,11 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
}
protected boolean resolve(final ClassNode type, final boolean testModuleImports, final boolean testDefaultImports, final boolean testStaticInnerClasses) {
- resolveGenericsTypes(type.getGenericsTypes());
- if (type.isResolved() || type.isPrimaryClassNode()) return true;
+ GenericsType[] genericsTypes = type.getGenericsTypes();
+ resolveGenericsTypes(genericsTypes);
+
+ if (type.isPrimaryClassNode()) return true;
+ if (type.isResolved()) return true;
if (type.isArray()) {
ClassNode element = type.getComponentType();
boolean resolved = resolve(element, testModuleImports, testDefaultImports, testStaticInnerClasses);
@@ -390,30 +393,33 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
return resolved;
}
- // test if vanilla name is current class name
- if (currentClass == type) return true;
-
String typeName = type.getName();
- GenericsType genericsType = genericParameterNames.get(new GenericsTypeName(typeName));
- if (genericsType != null) {
- type.setRedirect(genericsType.getType());
- type.setGenericsTypes(new GenericsType[]{genericsType});
+ GenericsType typeParameter = genericParameterNames.get(new GenericsTypeName(typeName));
+ if (typeParameter != null) {
+ type.setRedirect(typeParameter.getType());
+ type.setGenericsTypes(new GenericsType[]{typeParameter});
type.setGenericsPlaceHolder(true);
return true;
}
+ boolean resolved;
if (currentClass.getNameWithoutPackage().equals(typeName)) {
type.setRedirect(currentClass);
- return true;
+ resolved = true;
+ } else {
+ resolved = (!type.hasPackageName() && resolveNestedClass(type))
+ || resolveFromModule(type, testModuleImports)
+ || resolveFromCompileUnit(type)
+ || (testDefaultImports && !type.hasPackageName() && resolveFromDefaultImports(type))
+ || resolveToOuter(type)
+ || (testStaticInnerClasses && type.hasPackageName() && resolveFromStaticInnerClasses(type));
}
-
- return (!type.hasPackageName() && resolveNestedClass(type)) ||
- resolveFromModule(type, testModuleImports) ||
- resolveFromCompileUnit(type) ||
- (testDefaultImports && !type.hasPackageName() && resolveFromDefaultImports(type)) ||
- resolveToOuter(type) ||
- (testStaticInnerClasses && type.hasPackageName() && resolveFromStaticInnerClasses(type));
+ // GROOVY-10153: handle "C<? super T>"
+ if (resolved && genericsTypes != null) {
+ resolveWildcardBounding(genericsTypes, type);
+ }
+ return resolved;
}
protected boolean resolveNestedClass(final ClassNode type) {
@@ -1529,4 +1535,21 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
}
return genericsType.isResolved();
}
+
+ /**
+ * For cases like "Foo<? super Bar> -> Foo<T extends Baz>" there is an
+ * implicit upper bound on the wildcard type argument. It was unavailable at
+ * the time "? super Bar" was resolved but is present in type's redirect now.
+ */
+ private static void resolveWildcardBounding(final GenericsType[] typeArguments, final ClassNode type) {
+ for (int i = 0, n = typeArguments.length; i < n; i += 1) { GenericsType argument= typeArguments[i];
+ if (!argument.isWildcard() || argument.getUpperBounds() != null) continue;
+ GenericsType[] parameters = type.redirect().getGenericsTypes();
+ if (parameters != null && i < parameters.length) {
+ ClassNode implicitBound = parameters[i].getType();
+ if (!isObjectType(implicitBound))
+ argument.getType().setRedirect(implicitBound);
+ }
+ }
+ }
}
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 32c463ceb5..1cd5b77102 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -2935,6 +2935,21 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10153
+ void testCompatibleArgumentsForPlaceholders11() {
+ ['A', 'B', 'C'].each { T ->
+ assertScript """
+ class A {}
+ class B extends A {}
+ class C extends B {}
+ class Foo<T extends A> {}
+
+ Foo<? super C> foo = new Foo<$T>()
+ // ^ lower bound is C (explicit); upper bound is A (implicit)
+ """
+ }
+ }
+
void testIncompatibleArgumentsForPlaceholders1() {
shouldFailWithMessages '''
def <T extends Number> T test(T one, T two) { }