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 2026/03/07 16:54:26 UTC

(groovy) branch GROOVY_5_0_X updated: GROOVY-11870: STC: read type after setter checks

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

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


The following commit(s) were added to refs/heads/GROOVY_5_0_X by this push:
     new b2ebba73f5 GROOVY-11870: STC: read type after setter checks
b2ebba73f5 is described below

commit b2ebba73f5e2770d57bfdbb2fe2c73fe4ae5503d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Mar 7 10:26:53 2026 -0600

    GROOVY-11870: STC: read type after setter checks
    
    5_0_X backport
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  7 +++++--
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 23 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 2 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 90e217825c..07bb03ac47 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -848,17 +848,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 return;
             }
 
+            ClassNode lType;
             leftExpression.visit(this);
-            ClassNode lType = getType(leftExpression);
-            var setterInfo  = removeSetterInfo(leftExpression);
+            var setterInfo = removeSetterInfo(leftExpression);
             if (setterInfo != null) {
                 if (ensureValidSetter(expression, leftExpression, rightExpression, setterInfo)) {
                     return;
                 }
+                lType = getType(leftExpression); // GROOVY-11870
             } else {
                 if (op == EQUAL) {
                     lType = getOriginalDeclarationType(leftExpression);
                     applyTargetType(lType, rightExpression);
+                } else {
+                    lType = getType(leftExpression);
                 }
                 rightExpression.visit(this);
             }
diff --git a/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy
index 670cc96374..d7aeb4da5b 100644
--- a/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy
@@ -611,6 +611,29 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-11870
+    void testForLoopWithAssignment3() {
+        assertScript '''
+            class Pogo {
+                private List<Long> x
+                List<Long> getList() { x }
+                void setList(List<Long> list) { x = list }
+            }
+
+            void proc(List<Pogo> pogos) {
+                for (pogo in pogos) {
+                    pogo.list = [] // Cannot assign ArrayList<Object> to: List<Long>
+                    def item = 42L
+                    pogo.list.add(item)
+                }
+            }
+
+            def pogo = new Pogo()
+            proc([ pogo ])
+            assert pogo.list[0] == 42L
+        '''
+    }
+
     void testWhileLoopWithAssignment() {
         shouldFailWithMessages '''
             def x = '123'