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/08/30 14:53:26 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-10294: STC: track assign `null` to variable within `if` or `else`

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

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


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 612a9e9966 GROOVY-10294: STC: track assign `null` to variable within `if` or `else`
612a9e9966 is described below

commit 612a9e996629b789c8240e066ce7869fdad75eca
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Oct 30 18:49:03 2021 -0500

    GROOVY-10294: STC: track assign `null` to variable within `if` or `else`
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 43 ++++++++++------------
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 24 +++++++++---
 2 files changed, 38 insertions(+), 29 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 3087eda029..1cb2ad2819 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -880,8 +880,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
 
                 // track conditional assignment
-                if (!isNullConstant(rightExpression)
-                        && leftExpression instanceof VariableExpression
+                if (leftExpression instanceof VariableExpression
                         && typeCheckingContext.ifElseForWhileAssignmentTracker != null) {
                     Variable accessedVariable = ((VariableExpression) leftExpression).getAccessedVariable();
                     if (accessedVariable instanceof Parameter) {
@@ -1050,14 +1049,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected ClassNode getOriginalDeclarationType(final Expression lhs) {
         if (lhs instanceof VariableExpression) {
             Variable var = findTargetVariable((VariableExpression) lhs);
-            if (var instanceof PropertyNode) {
-                // Do NOT trust the type of the property node!
-                return getType(lhs);
+            if (!(var instanceof DynamicVariable || var instanceof PropertyNode)) {
+                return var.getOriginType();
             }
-            if (var instanceof DynamicVariable) return getType(lhs);
-            return var.getOriginType();
-        }
-        if (lhs instanceof FieldExpression) {
+        } else if (lhs instanceof FieldExpression) {
             return ((FieldExpression) lhs).getField().getOriginType();
         }
         return getType(lhs);
@@ -4088,18 +4083,18 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private void restoreTypeBeforeConditional() {
         typeCheckingContext.ifElseForWhileAssignmentTracker.forEach((var, types) -> {
-            ClassNode originType = types.get(0);
-            storeType(var, originType);
+            var.putNodeMetaData(INFERRED_TYPE, types.get(0));
         });
     }
 
     protected Map<VariableExpression, ClassNode> popAssignmentTracking(final Map<VariableExpression, List<ClassNode>> oldTracker) {
         Map<VariableExpression, ClassNode> assignments = new HashMap<>();
         typeCheckingContext.ifElseForWhileAssignmentTracker.forEach((var, types) -> {
-            ClassNode type = types.stream().filter(Objects::nonNull) // GROOVY-6099
-                .reduce(WideningCategories::lowestUpperBound).get();
-            assignments.put(var, type);
-            storeType(var, type);
+            types.stream().filter(t -> t != null && t != UNKNOWN_PARAMETER_TYPE) // GROOVY-6099, GROOVY-10294
+                    .reduce(WideningCategories::lowestUpperBound).ifPresent(type -> {
+                assignments.put(var, type);
+                storeType(var, type);
+            });
         });
         typeCheckingContext.ifElseForWhileAssignmentTracker = oldTracker;
         return assignments;
@@ -4348,15 +4343,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (exp instanceof VariableExpression) {
             VariableExpression var = (VariableExpression) exp;
             Variable accessedVariable = var.getAccessedVariable();
-            if (accessedVariable != exp && accessedVariable instanceof VariableExpression) {
-                storeType((VariableExpression) accessedVariable, cn);
-            }
-            if (accessedVariable instanceof Parameter
-                    || (accessedVariable instanceof PropertyNode
-                        && ((PropertyNode) accessedVariable).getField().isSynthetic())) {
-                ((ASTNode) accessedVariable).putNodeMetaData(INFERRED_TYPE, cn);
-            }
-            if (var.isClosureSharedVariable() && cn != null) {
+            if (accessedVariable instanceof VariableExpression) {
+                if (accessedVariable != exp)
+                    storeType((VariableExpression) accessedVariable, cn);
+            } else if (accessedVariable instanceof Parameter
+                    || accessedVariable instanceof PropertyNode
+                    && ((PropertyNode) accessedVariable).getField().isSynthetic()) {
+                ((AnnotatedNode) accessedVariable).putNodeMetaData(INFERRED_TYPE, cn);
+            }
+            if (cn != null && var.isClosureSharedVariable()) {
                 List<ClassNode> assignedTypes = typeCheckingContext.closureSharedVariablesAssignmentTypes.computeIfAbsent(var, k -> new LinkedList<ClassNode>());
                 assignedTypes.add(cn);
             }
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index 752c9c973b..b83c8eb5d5 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -952,14 +952,28 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
     // GROOVY-5535
     void testAssignToNullInsideIf() {
         assertScript '''
-            Date foo() {
-                Date result = new Date()
+            Date test() {
+                Date x = new Date()
                 if (true) {
-                    result = null
+                    x = null
                 }
-                return result
+                x
             }
-            assert foo() == null
+            assert test() == null
+        '''
+    }
+
+    // GROOVY-10294
+    void testAssignToNullInsideIf2() {
+        assertScript '''
+            CharSequence test() {
+                def x = 'works'
+                if (false) {
+                    x = null
+                }
+                x
+            }
+            assert test() == 'works'
         '''
     }