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 920970323e GROOVY-11817: SC: dynamic property or method call keeps 
method static
920970323e is described below

commit 920970323efc35c46dec6ec8bfbeabac80bdb969
Author: Eric Milles <[email protected]>
AuthorDate: Mon Dec 15 11:11:42 2025 -0600

    GROOVY-11817: SC: dynamic property or method call keeps method static
    
    - prevent static invocation writer and dynamic call site writer error
    
    5_0_X backport
---
 .../groovy/classgen/AsmClassGenerator.java         | 11 +++---
 .../groovy/classgen/asm/DelegatingController.java  |  6 ++++
 .../groovy/classgen/asm/WriterController.java      |  5 +++
 .../classgen/asm/sc/StaticInvocationWriter.java    |  7 ++--
 .../asm/sc/StaticTypesWriterController.java        | 15 +++++---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  4 +--
 .../asm/sc/MixedModeStaticCompilationTest.groovy   | 40 ++++++++++++++++++----
 7 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java 
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index fe6acf45bf..8f2b726614 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -97,6 +97,7 @@ import org.codehaus.groovy.ast.stmt.WhileStatement;
 import org.codehaus.groovy.ast.tools.WideningCategories;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.classgen.asm.BytecodeVariable;
+import org.codehaus.groovy.classgen.asm.CallSiteWriter;
 import org.codehaus.groovy.classgen.asm.CompileStack;
 import org.codehaus.groovy.classgen.asm.MethodCaller;
 import org.codehaus.groovy.classgen.asm.MethodCallerMultiAdapter;
@@ -1185,12 +1186,14 @@ public class AsmClassGenerator extends ClassGenerator {
             return;
         }
 
-        if (adapter == getGroovyObjectProperty && propertyName != null && 
!pexp.isSpreadSafe()) { // TODO: spread safe should be handled by each
-            
controller.getCallSiteWriter().makeGroovyObjectGetPropertySite(objectExpression,
 propertyName, pexp.isSafe(), pexp.isImplicitThis());
+        CallSiteWriter callSiteWriter = controller.getCallSiteWriterFor(pexp); 
// GROOVY-11817
+
+        if (adapter == getGroovyObjectProperty && propertyName != null && 
!pexp.isSpreadSafe()) { // TODO: propagate spread safe
+            callSiteWriter.makeGroovyObjectGetPropertySite(objectExpression, 
propertyName, pexp.isSafe(), pexp.isImplicitThis());
         } else if (adapter == getProperty && propertyName != null && 
!pexp.isSpreadSafe()) {
-            
controller.getCallSiteWriter().makeGetPropertySite(objectExpression, 
propertyName, pexp.isSafe(), pexp.isImplicitThis());
+            callSiteWriter.makeGetPropertySite(objectExpression, propertyName, 
pexp.isSafe(), pexp.isImplicitThis());
         } else {
-            
controller.getCallSiteWriter().fallbackAttributeOrPropertySite(pexp, 
objectExpression, propertyName, adapter);
+            callSiteWriter.fallbackAttributeOrPropertySite(pexp, 
objectExpression, propertyName, adapter);
         }
     }
 
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
index 3029237535..031fd27246 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
@@ -22,6 +22,7 @@ import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.InterfaceHelperClassNode;
 import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.GeneratorContext;
 import org.codehaus.groovy.control.SourceUnit;
@@ -64,6 +65,11 @@ public class DelegatingController extends WriterController {
         return delegationController.getCallSiteWriter();
     }
 
+    @Override
+    public CallSiteWriter getCallSiteWriterFor(final Expression expression) {
+        return delegationController.getCallSiteWriterFor(expression);
+    }
+
     @Override
     public StatementWriter getStatementWriter() {
         return delegationController.getStatementWriter();
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index 6c26671836..0968583dd8 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -23,6 +23,7 @@ import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.InterfaceHelperClassNode;
 import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.GeneratorContext;
 import org.codehaus.groovy.classgen.asm.indy.IndyBinHelper;
@@ -210,6 +211,10 @@ public class WriterController {
         return callSiteWriter;
     }
 
+    public CallSiteWriter getCallSiteWriterFor(final Expression expression) {
+        return callSiteWriter;
+    }
+
     public ClosureWriter getClosureWriter() {
         return closureWriter;
     }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index 816df9717a..914ec67217 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -469,11 +469,8 @@ public class StaticInvocationWriter extends 
InvocationWriter {
     @Override
     public void makeCall(final Expression origin, final Expression receiver, 
final Expression message, final Expression arguments, final 
MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe, 
final boolean implicitThis) {
         if (origin.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION) != 
null) {
-            StaticTypesWriterController staticController = 
(StaticTypesWriterController) controller;
-            if (origin instanceof MethodCallExpression) {
-                ((MethodCallExpression) origin).setMethodTarget(null);
-            }
-            InvocationWriter dynamicInvocationWriter = 
staticController.getRegularInvocationWriter();
+            if (origin instanceof MethodCallExpression) 
((MethodCallExpression) origin).setMethodTarget(null); // ensure dynamic resolve
+            InvocationWriter dynamicInvocationWriter = 
((StaticTypesWriterController) controller).getRegularInvocationWriter();
             dynamicInvocationWriter.makeCall(origin, receiver, message, 
arguments, adapter, safe, spreadSafe, implicitThis);
             return;
         }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
index 5a7e216c77..78ceed9196 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
@@ -21,6 +21,7 @@ package org.codehaus.groovy.classgen.asm.sc;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.GeneratorContext;
 import org.codehaus.groovy.classgen.asm.BinaryExpressionHelper;
@@ -37,10 +38,10 @@ import 
org.codehaus.groovy.classgen.asm.UnaryExpressionHelper;
 import org.codehaus.groovy.classgen.asm.WriterController;
 import 
org.codehaus.groovy.classgen.asm.indy.sc.IndyStaticTypesMultiTypeDispatcher;
 import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.transform.stc.StaticTypesMarker;
 import org.objectweb.asm.ClassVisitor;
 
 import static 
org.codehaus.groovy.transform.sc.StaticCompilationVisitor.isStaticallyCompiled;
+import static 
org.codehaus.groovy.transform.stc.StaticTypesMarker.DYNAMIC_RESOLUTION;
 
 /**
  * An alternative {@link org.codehaus.groovy.classgen.asm.WriterController} 
which handles static types and method
@@ -103,14 +104,20 @@ public class StaticTypesWriterController extends 
DelegatingController {
 
     @Override
     public CallSiteWriter getCallSiteWriter() {
-        MethodNode methodNode = getMethodNode();
-        if (isInStaticallyCheckedMethod && (methodNode == null
-                || 
!Boolean.TRUE.equals(methodNode.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION))))
 {
+        if (isInStaticallyCheckedMethod) {
             return callSiteWriter;
         }
         return super.getCallSiteWriter();
     }
 
+    @Override
+    public CallSiteWriter getCallSiteWriterFor(final Expression expression) {
+        if (expression.getNodeMetaData(DYNAMIC_RESOLUTION) != null) {
+            return getRegularCallSiteWriter(); // GROOVY-6263
+        }
+        return getCallSiteWriter();
+    }
+
     public CallSiteWriter getRegularCallSiteWriter() {
         return super.getCallSiteWriter();
     }
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 bf4451ecae..a1ef0d5107 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -739,7 +739,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         PropertyExpression pexp = thisPropX(true, dynName);
         if (existsProperty(pexp, 
!typeCheckingContext.isTargetOfEnclosingAssignment(vexp))) {
             vexp.copyNodeMetaData(pexp.getObjectExpression());
-            for (Object key : new Object[]{IMPLICIT_RECEIVER, 
READONLY_PROPERTY, PV_FIELDS_ACCESS, PV_FIELDS_MUTATION, 
DIRECT_METHOD_CALL_TARGET}) {
+            for (Object key : new Object[]{DIRECT_METHOD_CALL_TARGET, 
DYNAMIC_RESOLUTION, IMPLICIT_RECEIVER, PV_FIELDS_ACCESS, PV_FIELDS_MUTATION, 
READONLY_PROPERTY}) {
                 vexp.putNodeMetaData(key, pexp.getNodeMetaData(key));
             }
             ClassNode type = pexp.getNodeMetaData(INFERRED_TYPE);
@@ -748,7 +748,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
             }
             if (type == null) type = OBJECT_TYPE;
             vexp.putNodeMetaData(INFERRED_TYPE, type); // GROOVY-11007
-            String receiver = vexp.getNodeMetaData(IMPLICIT_RECEIVER);
+            String receiver = pexp.getNodeMetaData(IMPLICIT_RECEIVER);
             Boolean dynamic = pexp.getNodeMetaData(DYNAMIC_RESOLUTION);
             // GROOVY-7701, GROOVY-7996: correct false assumption made by 
VariableScopeVisitor
             if (((receiver != null && !receiver.endsWith("owner")) || 
Boolean.TRUE.equals(dynamic))
diff --git 
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
 
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
index db6a514c57..3a9b0e59c8 100644
--- 
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
+++ 
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
@@ -186,7 +186,7 @@ final class MixedModeStaticCompilationTest extends 
StaticTypeCheckingTestCase im
         '''
     }
 
-    void testAllowMetaClass() {
+    void testMetaClassUsage() {
         assertScript '''
             @CompileStatic(extensions='groovy/transform/sc/MixedMode.groovy')
             void test() {
@@ -204,23 +204,49 @@ final class MixedModeStaticCompilationTest extends 
StaticTypeCheckingTestCase im
         '''
     }
 
-    void testRecognizeStaticMethodCall() {
+    void testDynamicClassMethod1() {
         assertScript '''
             @CompileStatic(extensions='groovy/transform/sc/MixedMode2.groovy')
             Map<String, Integer> foo() {
                 String.map()
             }
+            try {
+                String.metaClass.static.map = { -> [a:1,b:2] }
+                assert foo().values().sort() == [1,2]
+            } finally {
+                GroovySystem.getMetaClassRegistry().removeMetaClass(String)
+            }
+        '''
+    }
+
+    void testDynamicClassMethod2() {
+        assertScript '''
             @CompileStatic(extensions='groovy/transform/sc/MixedMode2.groovy')
-            List<Integer> bar() {
+            List<Integer> foo() {
                 Date.list()
             }
             try {
-                String.metaClass.static.map = { [a: 1, b:2 ]}
-                Date.metaClass.static.list = { [1,2] }
-                assert foo().values().sort() == bar()
+                Date.metaClass.static.list = { -> [1,2] }
+                assert foo() == [1,2]
+            } finally {
+                GroovySystem.getMetaClassRegistry().removeMetaClass(Date)
+            }
+        '''
+    }
+
+    // GROOVY-11817
+    void testDynamicClassMethod3() {
+        assertScript '''
+            @CompileStatic(extensions='groovy/transform/sc/MixedMode2.groovy')
+            def foo() {
+                def list_of_integer = Date.list()
+                def integer = list_of_integer[0]
+            }
+            try {
+                Date.metaClass.static.list = { -> [1,2] }
+                assert foo() == 1
             } finally {
                 GroovySystem.getMetaClassRegistry().removeMetaClass(Date)
-                GroovySystem.getMetaClassRegistry().removeMetaClass(String)
             }
         '''
     }

Reply via email to