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 c05a538d01 GROOVY-11856: STC: save inferred type of list and map
expressions
c05a538d01 is described below
commit c05a538d01062265f2eaa610a644a1e34296652c
Author: Eric Milles <[email protected]>
AuthorDate: Sat Feb 7 19:13:26 2026 -0600
GROOVY-11856: STC: save inferred type of list and map expressions
---
.../codehaus/groovy/classgen/asm/OperandStack.java | 46 +++++++++++-----------
.../transform/stc/StaticTypeCheckingVisitor.java | 8 +++-
src/test/groovy/bugs/Groovy10034.groovy | 12 ++++--
src/test/groovy/bugs/Groovy9126.groovy | 4 +-
4 files changed, 41 insertions(+), 29 deletions(-)
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..bac046633e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java
@@ -22,8 +22,6 @@ import org.apache.groovy.ast.tools.ClassNodeUtils;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.expr.CastExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
@@ -313,36 +311,40 @@ public class OperandStack {
doConvertAndCast(targetType,true);
}
- private void throwExceptionForNoStackElement(final int size, final
ClassNode targetType, final boolean coerce) {
- if (size > 0) return;
- StringBuilder sb = new StringBuilder();
- sb.append("Internal compiler error while compiling
").append(controller.getSourceUnit().getName()).append("\n");
- MethodNode methodNode = controller.getMethodNode();
- if (methodNode!=null) {
- sb.append("Method: ");
- sb.append(methodNode);
- sb.append("\n");
- }
- ConstructorNode constructorNode = controller.getConstructorNode();
- if (constructorNode!=null) {
+ private String missingOperand(final ClassNode targetType, final boolean
coerce) {
+ var sb = new StringBuilder("Internal compiler error while compiling ");
+ sb.append(controller.getSourceUnit().getName());
+ sb.append("\n");
+ var constructorNode = controller.getConstructorNode();
+ if (constructorNode != null) {
sb.append("Constructor: ");
- sb.append(methodNode);
+ sb.append(constructorNode);
sb.append("\n");
+ } else {
+ var methodNode = controller.getMethodNode();
+ if (methodNode != null) {
+ sb.append("Method: ");
+ sb.append(methodNode);
+ sb.append("\n");
+ }
}
- sb.append("Line ").append(controller.getLineNumber()).append(",");
- sb.append(" expecting ").append(coerce ? "coercion" :
"casting").append(" to ").append(targetType.toString(false));
+ sb.append("Line ").append(controller.getLineNumber()).append(",
expecting ").append(coerce ? "coercion" : "casting");
+ sb.append(" to ").append(ClassNodeUtils.formatTypeName(targetType));
sb.append(" but operand stack is empty");
- throw new ArrayIndexOutOfBoundsException(sb.toString());
+ return sb.toString();
}
private void doConvertAndCast(ClassNode targetType, final boolean coerce) {
int size = stack.size();
- throwExceptionForNoStackElement(size, targetType, coerce);
+ if (size == 0) {
+ throw new
ArrayIndexOutOfBoundsException(missingOperand(targetType, coerce));
+ }
ClassNode top = stack.get(size - 1);
- targetType = targetType.redirect();
- if (top == targetType /* for better performance */
- || ClassNodeUtils.isCompatibleWith(top, targetType)) return;
+ if (top == (targetType = targetType.redirect()) // quick check
+ || ClassNodeUtils.isCompatibleWith(top, targetType)) {
+ return;
+ }
if (coerce) {
controller.getInvocationWriter().coerce(top, targetType);
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 a1ef0d5107..7e39318a68 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5271,11 +5271,15 @@ trying: for (ClassNode[] signature : signatures) {
}
if (node instanceof ListExpression) {
- return inferListExpressionType((ListExpression) node);
+ type = inferListExpressionType((ListExpression) node);
+ node.putNodeMetaData(INFERRED_TYPE, type);
+ return type;
}
if (node instanceof MapExpression) {
- return inferMapExpressionType((MapExpression) node);
+ type = inferMapExpressionType((MapExpression) node);
+ node.putNodeMetaData(INFERRED_TYPE, type);
+ return type;
}
if (node instanceof RangeExpression) {
diff --git a/src/test/groovy/bugs/Groovy10034.groovy
b/src/test/groovy/bugs/Groovy10034.groovy
index bed617b7a7..7dc6baefa5 100644
--- a/src/test/groovy/bugs/Groovy10034.groovy
+++ b/src/test/groovy/bugs/Groovy10034.groovy
@@ -31,8 +31,14 @@ final class Groovy10034 extends AbstractBytecodeTestCase {
["x"].toArray(new String[0])
}
'''
- int offset = result.indexOf('ANEWARRAY java/lang/String',
result.indexOf('--BEGIN--'))
- assert result.hasStrictSequence(['ANEWARRAY
java/lang/String','INVOKEVIRTUAL java/util/ArrayList.toArray'], offset)
- // there should be no 'INVOKEDYNAMIC cast' instruction here: ^
+ int offset = result.indexOf('INVOKESTATIC',
result.indexOf('--BEGIN--'))
+ assert result.hasStrictSequence([
+ 'INVOKESTATIC
org/codehaus/groovy/runtime/ScriptBytecodeAdapter.createList',
+ 'CHECKCAST java/util/ArrayList', // not 'INVOKEDYNAMIC cast'
+ 'ICONST_0',
+ 'ANEWARRAY java/lang/String',
+ // no 'INVOKEDYNAMIC cast' to Object[]
+ 'INVOKEVIRTUAL java/util/ArrayList.toArray'
+ ], offset)
}
}
diff --git a/src/test/groovy/bugs/Groovy9126.groovy
b/src/test/groovy/bugs/Groovy9126.groovy
index baadd5dc72..b2f804a26b 100644
--- a/src/test/groovy/bugs/Groovy9126.groovy
+++ b/src/test/groovy/bugs/Groovy9126.groovy
@@ -19,12 +19,12 @@
package bugs
import org.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase
-import org.junit.Test
+import org.junit.jupiter.api.Test
final class Groovy9126 extends AbstractBytecodeTestCase {
@Test
- void testUnreachableBytecode() {
+ void testUnreachableBytecode1() {
assert compile(method:'nonVoidMethod',
'''@groovy.transform.CompileStatic
int nonVoidMethod() {
1 * 1