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 2025/10/03 23:14:32 UTC

(groovy) branch master updated (04c585502a -> b2707d2a72)

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

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


    from 04c585502a GROOVY-11292, GROOVY-11750, GROOVY-11768: non-sealed super class
     new c7cf9575e3 GROOVY-11769: add test case
     new b2707d2a72 minor items

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../groovy/classgen/AsmClassGenerator.java         | 35 ++++++++++------------
 .../codehaus/groovy/classgen/asm/OperandStack.java |  2 +-
 .../groovy/transform/stc/CoercionSTCTest.groovy    | 15 ++++++++++
 .../asm/sc/CoercionStaticCompileTests.groovy       |  8 +++++
 4 files changed, 39 insertions(+), 21 deletions(-)


(groovy) 01/02: GROOVY-11769: add test case

Posted by em...@apache.org.
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

commit c7cf9575e3f7d2f1ce93b615233a85d38c1e5ab5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Oct 3 18:10:08 2025 -0500

    GROOVY-11769: add test case
---
 .../groovy/groovy/transform/stc/CoercionSTCTest.groovy    | 15 +++++++++++++++
 .../classgen/asm/sc/CoercionStaticCompileTests.groovy     |  8 ++++++++
 2 files changed, 23 insertions(+)

diff --git a/src/test/groovy/groovy/transform/stc/CoercionSTCTest.groovy b/src/test/groovy/groovy/transform/stc/CoercionSTCTest.groovy
index b3cd48094f..79dc18cb9b 100644
--- a/src/test/groovy/groovy/transform/stc/CoercionSTCTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/CoercionSTCTest.groovy
@@ -211,6 +211,21 @@ class CoercionSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testCastObjectToInterface() {
+        assertScript '''
+            List<Object> m(object) {
+                if (object == null) return new ArrayList<>()
+                if (object instanceof Collection) return new ArrayList<Object>((Collection) object)
+                return [object]
+            }
+            def item = 0
+            def list = [1,2]
+            assert m(null).size() == 0
+            assert m(item).size() == 1
+            assert m(list).size() == 2
+        '''
+    }
+
     void testCastInterfaceToSubclass() {
         assertScript '''
             interface A {
diff --git a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CoercionStaticCompileTests.groovy b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CoercionStaticCompileTests.groovy
index 7506ceb415..d87870cb10 100644
--- a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CoercionStaticCompileTests.groovy
+++ b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CoercionStaticCompileTests.groovy
@@ -24,4 +24,12 @@ import groovy.transform.stc.CoercionSTCTest
  * Unit tests for static compilation : coercions.
  */
 final class CoercionStaticCompileTests extends CoercionSTCTest implements StaticCompilationTestSupport {
+
+    @Override // GROOVY-11769
+    void testCastObjectToInterface() {
+        super.testCastObjectToInterface()
+        String bytecode = astTrees.values()[0][1]
+        bytecode = bytecode.substring(bytecode.indexOf('m(Ljava/lang/Object;)'))
+        assert bytecode.count('CHECKCAST') == 1 // guarded typecast isn't groovy
+    }
 }


(groovy) 02/02: minor items

Posted by em...@apache.org.
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

commit b2707d2a72a5ba84866de9c9df3b8dbbf0119aa2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Oct 3 18:10:48 2025 -0500

    minor items
---
 .../groovy/classgen/AsmClassGenerator.java         | 35 ++++++++++------------
 .../codehaus/groovy/classgen/asm/OperandStack.java |  2 +-
 2 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index c453f4dda7..11f7db8c43 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -94,7 +94,6 @@ import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
 import org.codehaus.groovy.ast.stmt.ThrowStatement;
 import org.codehaus.groovy.ast.stmt.TryCatchStatement;
 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.CompileStack;
@@ -132,7 +131,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.TreeMap;
 import java.util.function.Consumer;
 
 import static org.apache.groovy.ast.tools.ClassNodeUtils.getField;
@@ -158,6 +156,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.maybeFallsThrough;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
 import static org.codehaus.groovy.ast.tools.ParameterUtils.isVargs;
+import static org.codehaus.groovy.ast.tools.WideningCategories.implementsInterfaceOrSubclassOf;
 import static org.codehaus.groovy.transform.SealedASTTransformation.sealedNative;
 import static org.codehaus.groovy.transform.SealedASTTransformation.sealedSkipAnnotation;
 import static org.objectweb.asm.Opcodes.AALOAD;
@@ -994,8 +993,8 @@ public class AsmClassGenerator extends ClassGenerator {
 
     @Override
     public void visitCastExpression(final CastExpression castExpression) {
-        Expression subExpression = castExpression.getExpression();
-        subExpression.visit(this);
+        Expression expression = castExpression.getExpression();
+        expression.visit(this);
 
         ClassNode type = castExpression.getType();
         if (isObjectType(type)) return;
@@ -1004,19 +1003,13 @@ public class AsmClassGenerator extends ClassGenerator {
         OperandStack operandStack = controller.getOperandStack();
         if (castExpression.isCoerce()) {
             operandStack.doAsType(type);
+        } else if (isNullConstant(expression) && !isPrimitiveType(type)) {
+            operandStack.replace(type);
+        } else if (castExpression.isStrict() || (!isPrimitiveType(type) && implementsInterfaceOrSubclassOf(typeOf(expression), type))) {
+            BytecodeHelper.doCast(controller.getMethodVisitor(), type); // checkcast or unbox
+            operandStack.replace(type);
         } else {
-            if (isNullConstant(subExpression) && !isPrimitiveType(type)) {
-                operandStack.replace(type);
-            } else {
-                ClassNode subExprType = controller.getTypeChooser().resolveType(subExpression, controller.getClassNode());
-                if (castExpression.isStrict() ||
-                        (!isPrimitiveType(type) && WideningCategories.implementsInterfaceOrSubclassOf(subExprType, type))) {
-                    BytecodeHelper.doCast(controller.getMethodVisitor(), type);
-                    operandStack.replace(type);
-                } else {
-                    operandStack.doGroovyCast(type);
-                }
-            }
+            operandStack.doGroovyCast(type);
         }
     }
 
@@ -1192,7 +1185,7 @@ public class AsmClassGenerator extends ClassGenerator {
             return !controller.isStaticContext(); // TODO: not @POJO
         }
 
-        ClassNode objectExpressionType = controller.getTypeChooser().resolveType(objectExpression, controller.getClassNode());
+        ClassNode objectExpressionType = typeOf(objectExpression);
         if (isObjectType(objectExpressionType)) objectExpressionType = objectExpression.getType();
         return objectExpressionType.isDerivedFromGroovyObject();
     }
@@ -1456,9 +1449,7 @@ public class AsmClassGenerator extends ClassGenerator {
             pexp.visit(this);
 
             if (!compileStack.isLHS() && !expression.isDynamicTyped()) {
-                ClassNode variableType = controller.getTypeChooser()
-                    .resolveType(expression, controller.getClassNode());
-                controller.getOperandStack().doGroovyCast(variableType);
+                controller.getOperandStack().doGroovyCast(typeOf(expression));
             }
         }
 
@@ -2441,4 +2432,8 @@ public class AsmClassGenerator extends ClassGenerator {
     public void throwException(final String message) {
         throw new RuntimeParserException(message, currentASTNode);
     }
+
+    private ClassNode typeOf(final Expression expr) {
+        return controller.getTypeChooser().resolveType(expr, controller.getClassNode());
+    }
 }
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java b/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java
index 4ff4538551..aee1e7c598 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java
@@ -375,7 +375,7 @@ public class OperandStack {
         } else {
             top = stack.get(size - 1);
             if (!WideningCategories.implementsInterfaceOrSubclassOf(top, targetType)) {
-                BytecodeHelper.doCast(mv,targetType);
+                BytecodeHelper.doCast(mv, targetType);
             }
         }
         replace(targetType);