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 6317685dfc GROOVY-10688: STC: common generics resolver for assign and
elvis/ternary
6317685dfc is described below
commit 6317685dfcb4dae62eb471d860f1e6745ae31126
Author: Eric Milles <[email protected]>
AuthorDate: Mon Jul 25 14:23:46 2022 -0500
GROOVY-10688: STC: common generics resolver for assign and elvis/ternary
---
.../transform/stc/StaticTypeCheckingVisitor.java | 76 +++++++++++-----------
.../transform/stc/TernaryOperatorSTCTest.groovy | 20 ++++++
2 files changed, 57 insertions(+), 39 deletions(-)
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 5bba1ed565..36b3fa4298 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -841,33 +841,8 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
if (rightExpression instanceof ConstructorCallExpression)
inferDiamondType((ConstructorCallExpression)
rightExpression, lType);
- if (lType.isUsingGenerics()
- && missesGenericsTypes(resultType)
- // GROOVY-10324, GROOVY-10342, et al.
- && !resultType.isGenericsPlaceHolder()) {
- // unchecked assignment
- // List<Type> list = new LinkedList()
- // Iterable<Type> iter = new LinkedList()
- // Collection<Type> coll = Collections.emptyList()
- // Collection<Type> view = ConcurrentHashMap.newKeySet()
-
- // the inferred type of the binary expression is the type
of the RHS
- // "completed" with generics type information available
from the LHS
- if (lType.equals(resultType)) {
- // GROOVY-6126, GROOVY-6558, GROOVY-6564, et al.
- if (!lType.isGenericsPlaceHolder()) resultType = lType;
- } else {
- // GROOVY-5640, GROOVY-9033, GROOVY-10220,
GROOVY-10235, et al.
- Map<GenericsTypeName, GenericsType> gt = new
HashMap<>();
- extractGenericsConnections(gt, resultType,
resultType.redirect());
- ClassNode sc = resultType;
- do { sc = getNextSuperClass(sc, lType);
- } while (sc != null && !sc.equals(lType));
- extractGenericsConnections(gt, lType, sc);
-
- resultType = applyGenericsContext(gt,
resultType.redirect());
- }
- }
+ // handle unchecked assignment: List<Type> list = []
+ resultType = adjustForTargetType(resultType, lType);
ClassNode originType =
getOriginalDeclarationType(leftExpression);
typeCheckAssignment(expression, leftExpression, originType,
rightExpression, resultType);
@@ -4294,25 +4269,48 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
return isSAMType(targetType) ? targetType : type;
}
- ClassNode sourceType =
Optional.ofNullable(getInferredReturnType(expr)).orElse(type);
+ if (targetType == null)
+ targetType = type.getPlainNodeReference();
+ if (type == UNKNOWN_PARAMETER_TYPE) return targetType;
- if (expr instanceof ConstructorCallExpression) { // GROOVY-9972,
GROOVY-9983
- // GROOVY-10114: type parameter(s) could be inferred from call
arguments
- if (targetType == null) targetType =
sourceType.getPlainNodeReference();
+ if (expr instanceof ConstructorCallExpression) { // GROOVY-9972,
GROOVY-9983, GROOVY-10114
inferDiamondType((ConstructorCallExpression) expr, targetType);
- return sourceType;
}
- if (targetType == null) return sourceType;
+ return adjustForTargetType(type, targetType);
+ }
+
+ private static ClassNode adjustForTargetType(final ClassNode resultType,
final ClassNode targetType) {
+ if (targetType.isUsingGenerics()
+ && missesGenericsTypes(resultType)
+ // GROOVY-10324, GROOVY-10342, et al.
+ && !resultType.isGenericsPlaceHolder()) {
+ // unchecked assignment
+ // List<Type> list = new LinkedList()
+ // Iterable<Type> iter = new LinkedList()
+ // Collection<Type> col1 = Collections.emptyList()
+ // Collection<Type> col2 = Collections.emptyList() ?: []
+ // Collection<Type> view = ConcurrentHashMap.newKeySet()
- if (!isPrimitiveType(getUnwrapper(targetType)) &&
!isObjectType(targetType)
- && !sourceType.isGenericsPlaceHolder() &&
missesGenericsTypes(sourceType)) {
- // unchecked assignment with ternary/elvis, like "List<T> list =
listOfT ?: []"
- // the inferred type is the RHS type "completed" with generics
information from LHS
- return GenericsUtils.parameterizeType(targetType,
sourceType.getPlainNodeReference());
+ // the inferred type of the binary expression is the type of the
RHS
+ // "completed" with generics type information available from the
LHS
+ if (targetType.equals(resultType)) {
+ // GROOVY-6126, GROOVY-6558, GROOVY-6564, et al.
+ if (!targetType.isGenericsPlaceHolder()) return targetType;
+ } else {
+ // GROOVY-5640, GROOVY-9033, GROOVY-10220, GROOVY-10235,
GROOVY-10688, et al.
+ Map<GenericsTypeName, GenericsType> gt = new HashMap<>();
+ extractGenericsConnections(gt, resultType,
resultType.redirect());
+ ClassNode sc = resultType;
+ do { sc = getNextSuperClass(sc, targetType);
+ } while (sc != null && !sc.equals(targetType));
+ extractGenericsConnections(gt, targetType, sc);
+
+ return applyGenericsContext(gt, resultType.redirect());
+ }
}
- return sourceType != UNKNOWN_PARAMETER_TYPE ? sourceType : targetType;
+ return resultType;
}
private static boolean isTypeSource(final Expression expr, final
Expression right) {
diff --git a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
index 40dd80722e..98a0e06569 100644
--- a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
@@ -166,6 +166,20 @@ class TernaryOperatorSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10688
+ void testTypeParameterTypeParameter3() {
+ assertScript '''
+ class A<T,U> {
+ }
+ <T> void test(
+ A<Double, ? extends T> x) {
+ A<Double, ? extends T> y = x
+ A<Double, ? extends T> z = true ? y : x
+ }
+ test(null)
+ '''
+ }
+
// GROOVY-10271
void testFunctionalInterfaceTarget1() {
['true', 'false'].each { flag ->
@@ -274,6 +288,12 @@ class TernaryOperatorSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ void testCommonInterface3() {
+ assertScript '''import static java.util.concurrent.ConcurrentHashMap.*
+ Set<Integer> integers = false ? new HashSet<>() : newKeySet()
+ '''
+ }
+
// GROOVY-10130
void testInstanceofGuard() {
assertScript '''