You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/06/13 13:40:23 UTC

[groovy] 04/06: GROOVY-7701: do not cast RHS before LHS of assignment is visited

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

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

commit 1c779b7baf6c9e4ea9839ed5d36b6adbf1e2a124
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jun 4 13:59:12 2020 -0500

    GROOVY-7701: do not cast RHS before LHS of assignment is visited
    
    (cherry picked from commit 3bf8f9fe71aaa471a72029d410cedbffa83d52fb)
---
 .../classgen/asm/BinaryExpressionHelper.java       |  8 ++----
 src/test/groovy/lang/ClosureResolvingTest.groovy   | 31 +++++++++++++++++++---
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
index 02f02e9..0e3f623 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
@@ -382,8 +382,8 @@ public class BinaryExpressionHelper {
             operandStack.loadOrStoreVariable(var, false);
             return;
         }
-
-        // let's evaluate the RHS and store the result
+        // evaluate the RHS and store the result
+        // TODO: LHS has not been visited, it could be a variable in a closure and type chooser is not aware.
         ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
         if (rightExpression instanceof ListExpression && lhsType.isArray()) {
             ListExpression list = (ListExpression) rightExpression;
@@ -467,11 +467,7 @@ public class BinaryExpressionHelper {
         } else {
             // normal assignment
             int mark = operandStack.getStackLength();
-            // to leave a copy of the rightExpression value on the stack after the assignment.
             rhsValueLoader.visit(acg);
-            TypeChooser typeChooser = controller.getTypeChooser();
-            ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode());
-            operandStack.doGroovyCast(targetType);
             leftExpression.visit(acg);
             operandStack.remove(operandStack.getStackLength() - mark);
         }
diff --git a/src/test/groovy/lang/ClosureResolvingTest.groovy b/src/test/groovy/lang/ClosureResolvingTest.groovy
index 14f27a2..69d2932 100644
--- a/src/test/groovy/lang/ClosureResolvingTest.groovy
+++ b/src/test/groovy/lang/ClosureResolvingTest.groovy
@@ -84,7 +84,33 @@ class ClosureResolvingTest extends GroovyTestCase {
         assertEquals "stuff", c.call()
         c.delegate = new TestResolve1()
         assertEquals "foo", c.call()
+    }
+
+    // GROOVY-7701
+    void testResolveDelegateFirst2() {
+        assertScript '''
+            class Foo {
+                List type
+            }
+            class Bar {
+                int type = 10
+                List<Foo> something = { ->
+                    List<Foo> tmp = []
+                    def foo = new Foo()
+                    foo.with {
+                        type = ['String']
+                    //  ^^^^ should be Foo.type, not Bar.type
+                    }
+                    tmp.add(foo)
+                    return tmp
+                }()
+            }
 
+            def bar = new Bar()
+            assert bar.type == 10
+            assert bar.something*.type == [['String']]
+            assert bar.type == 10
+        '''
     }
 
     void testResolveOwnerFirst() {
@@ -125,7 +151,6 @@ class ClosureResolvingTest extends GroovyTestCase {
         c.resolveStrategy = Closure.DELEGATE_ONLY
         c.delegate = new TestResolve1()
         assertEquals "foo", c.call()
-
     }
 
     void testResolveOwnerOnly() {
@@ -142,7 +167,6 @@ class ClosureResolvingTest extends GroovyTestCase {
         c.resolveStrategy = Closure.OWNER_ONLY
         c.delegate = new TestResolve1()
         assertEquals "stuff", c.call()
-
     }
 
     void testOwnerDelegateChain() {
@@ -196,10 +220,9 @@ class TestResolve2 {
 class TestResolve3 {
     def del;
 
-    String toString() {del}
+    String toString() { del }
 
     def whoisThis() { return this }
 
     def met() { return "I'm the method inside '" + del + "'" }
 }
-