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:44:58 UTC

(groovy) branch master 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 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 d99e5fd4d5 GROOVY-11870: STC: read type after setter checks
d99e5fd4d5 is described below

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

    GROOVY-11870: STC: read type after setter checks
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  9 +++++---
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 24 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 3 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 ac94f18e23..fb35f16fce 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 {
             // GROOVY-7971, GROOVY-8965, GROOVY-10096, GROOVY-10702, et al.
             if (op == LOGICAL_OR) typeCheckingContext.pushTemporaryTypeInfo();
 
+            ClassNode lType;
             leftExpression.visit(this);
-            ClassNode lType = getType(leftExpression);
-            var setterInfo  = removeSetterInfo(leftExpression);
-            if (setterInfo != null) { assert op != LOGICAL_OR ;
+            var setterInfo = removeSetterInfo(leftExpression);
+            if (setterInfo != null) { assert op != LOGICAL_OR;
                 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);
                 }
                 if (op != LOGICAL_OR) {
                     rightExpression.visit(this);
diff --git a/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy
index 5bc836d0ab..64df131143 100644
--- a/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy
@@ -668,6 +668,30 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-11870
+    @Test
+    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
+        '''
+    }
+
     @Test
     void testWhileLoopWithAssignment() {
         shouldFailWithMessages '''