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 '''

Reply via email to