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 168bb9bc07 cast implicit property and fix types of within-closure 
`this` conversion
168bb9bc07 is described below

commit 168bb9bc078ec7f68c47af4571ce0238496235f1
Author: Eric Milles <[email protected]>
AuthorDate: Tue Sep 17 04:22:44 2024 -0500

    cast implicit property and fix types of within-closure `this` conversion
---
 .../groovy/classgen/AsmClassGenerator.java         | 22 ++----
 .../classgen/asm/sc/StaticInvocationWriter.java    | 88 +++++++++++-----------
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |  4 +-
 .../test/builder/ObjectGraphBuilderTest.groovy     | 19 +++--
 src/test/groovy/bugs/Groovy8446.groovy             | 33 ++++----
 .../groovy/transform/stc/ClosuresSTCTest.groovy    | 20 +++--
 6 files changed, 83 insertions(+), 103 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java 
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index dba0284fab..b25c542500 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -896,18 +896,6 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getLambdaWriter().writeLambda(expression);
     }
 
-    /**
-     * Loads either this object or if we're inside a closure then load the top 
level owner
-     */
-    protected void loadThisOrOwner() {
-        ClassNode classNode = controller.getClassNode();
-        if (classNode.getOuterClass() == null) {
-            loadThis(VariableExpression.THIS_EXPRESSION);
-        } else {
-            fieldX(classNode.getDeclaredField("owner")).visit(this);
-        }
-    }
-
     /**
      * Generates byte code for constants.
      *
@@ -1417,11 +1405,17 @@ public class AsmClassGenerator extends ClassGenerator {
         if (variable != null) {
             controller.getOperandStack().loadOrStoreVariable(variable, 
expression.isUseReferenceDirectly());
         } else {
-            PropertyExpression pexp = thisPropX(true, expression.getName());
+            PropertyExpression pexp = thisPropX(/*implicit-this*/true, 
expression.getName());
             pexp.getProperty().setSourcePosition(expression);
             pexp.setType(expression.getType());
             pexp.copyNodeMetaData(expression);
             pexp.visit(this);
+
+            if (!compileStack.isLHS() && !expression.isDynamicTyped()) {
+                ClassNode variableType = controller.getTypeChooser()
+                    .resolveType(expression, controller.getClassNode());
+                controller.getOperandStack().doGroovyCast(variableType);
+            }
         }
 
         if (!compileStack.isLHS()) {
@@ -2375,7 +2369,7 @@ public class AsmClassGenerator extends ClassGenerator {
         OperandStack operandStack = controller.getOperandStack();
         if (controller.isInGeneratedFunction() && 
!controller.getCompileStack().isImplicitThis()) {
             mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Closure", 
"getThisObject", "()Ljava/lang/Object;", false);
-            ClassNode expectedType = 
controller.getTypeChooser().resolveType(thisOrSuper, 
controller.getOutermostClass());
+            ClassNode expectedType = 
controller.getTypeChooser().resolveType(thisOrSuper, controller.getThisType() );
             if (!isObjectType(expectedType) && !isPrimitiveType(expectedType)) 
{
                 BytecodeHelper.doCast(mv, expectedType);
                 operandStack.push(expectedType);
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 4e81f7b08b..8cf40bc7f8 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
@@ -79,10 +79,12 @@ import static 
org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isThisOrSuper;
 import static org.codehaus.groovy.ast.ClassHelper.isGStringType;
+import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
 import static org.codehaus.groovy.ast.ClassHelper.isObjectType;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
 import static org.codehaus.groovy.ast.ClassHelper.isStringType;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.attrX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
@@ -91,6 +93,7 @@ import static 
org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafe0;
 import static org.codehaus.groovy.transform.trait.Traits.isTrait;
 import static org.objectweb.asm.Opcodes.ACONST_NULL;
 import static org.objectweb.asm.Opcodes.ALOAD;
@@ -213,6 +216,33 @@ public class StaticInvocationWriter extends 
InvocationWriter {
         controller.getCompileStack().pop();
     }
 
+    private Expression thisObjectExpression(final ClassNode source, final 
ClassNode target) {
+        ClassNode thisType = source;
+        while (isGeneratedFunction(thisType)) {
+            thisType = thisType.getOuterClass();
+        }
+        Expression thisExpr;
+        if (isTrait(thisType.getOuterClass())) {
+            thisExpr = varX("thisObject"); // GROOVY-7242, GROOVY-8127
+        } else if (controller.isStaticContext()) {
+            thisExpr = varX("thisObject", 
makeClassSafe0(ClassHelper.CLASS_Type, thisType.asGenericsType()));
+        } else {
+            thisExpr = varX("thisObject", thisType);
+            // adjust for multiple levels of nesting
+            while (!thisType.isDerivedFrom(target) && 
!thisType.implementsInterface(target)) {
+                FieldNode thisZero = thisType.getDeclaredField("this$0");
+                if (thisZero != null) {
+                    thisExpr = attrX(thisExpr, "this$0");
+                    thisExpr.setType(thisZero.getType());
+                    thisType = thisType.getOuterClass();
+                    if (thisType != null) continue;
+                }
+                break;
+            }
+        }
+        return thisExpr;
+    }
+
     /**
      * Attempts to make a direct method call on a bridge method, if it exists.
      */
@@ -238,32 +268,22 @@ public class StaticInvocationWriter extends 
InvocationWriter {
             lookupClassNode = target.getDeclaringClass().redirect();
         }
         Map<MethodNode, MethodNode> bridges = 
lookupClassNode.getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS);
-        MethodNode bridge = bridges == null ? null : bridges.get(target);
+        MethodNode bridge = (bridges == null ? null : bridges.get(target));
         if (bridge != null) {
-            Expression fixedReceiver = receiver;
+            Expression newReceiver = receiver;
             if (implicitThis) {
                 if (!controller.isInGeneratedFunction()) {
                     if (!thisClass.isDerivedFrom(lookupClassNode))
-                        fixedReceiver = propX(classX(lookupClassNode), "this");
+                        newReceiver = propX(classX(lookupClassNode), "this");
                 } else if (thisClass != null) {
-                    ClassNode current = thisClass.getOuterClass();
-                    fixedReceiver = varX("thisObject", current);
-                    // adjust for multiple levels of nesting if needed
-                    while (current.getOuterClass() != null && 
!lookupClassNode.equals(current)) {
-                        FieldNode thisField = current.getField("this$0");
-                        current = current.getOuterClass();
-                        if (thisField != null) {
-                            fixedReceiver = propX(fixedReceiver, "this$0");
-                            fixedReceiver.setType(current);
-                        }
-                    }
+                    newReceiver = thisObjectExpression(thisClass, 
lookupClassNode);
                 }
             }
-            ArgumentListExpression newArgs = args(target.isStatic() ? nullX() 
: fixedReceiver);
+            ArgumentListExpression newArguments = args(target.isStatic() ? 
nullX() : newReceiver);
             for (Expression expression : args.getExpressions()) {
-                newArgs.addExpression(expression);
+                newArguments.addExpression(expression);
             }
-            return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, 
newArgs);
+            return writeDirectMethodCall(bridge, implicitThis, newReceiver, 
newArguments);
         }
         return false;
     }
@@ -284,22 +304,10 @@ public class StaticInvocationWriter extends 
InvocationWriter {
             List<Expression> argumentList = new ArrayList<>();
             if (emn.isStaticExtension()) {
                 argumentList.add(nullX());
+            } else if (!isThisOrSuper(receiver) || 
!controller.isInGeneratedFunction()) {
+                argumentList.add(receiver);
             } else {
-                Expression fixedReceiver = null;
-                if (isThisOrSuper(receiver) && classNode.getOuterClass() != 
null && controller.isInGeneratedFunction()) {
-                    ClassNode current = classNode.getOuterClass();
-                    fixedReceiver = varX("thisObject", current);
-                    // adjust for multiple levels of nesting if needed
-                    while (current.getOuterClass() != null && 
!classNode.equals(current)) {
-                        FieldNode thisField = current.getField("this$0");
-                        current = current.getOuterClass();
-                        if (thisField != null) {
-                            fixedReceiver = propX(fixedReceiver, "this$0");
-                            fixedReceiver.setType(current);
-                        }
-                    }
-                }
-                argumentList.add(fixedReceiver != null ? fixedReceiver : 
receiver);
+                argumentList.add(thisObjectExpression(classNode, 
target.getDeclaringClass()));
             }
             argumentList.addAll(args.getExpressions());
             loadArguments(argumentList, parameters);
@@ -367,20 +375,8 @@ public class StaticInvocationWriter extends 
InvocationWriter {
                     && controller.isInGeneratedFunction()
                     && !classNode.isDerivedFrom(target.getDeclaringClass())
                     && 
!classNode.implementsInterface(target.getDeclaringClass())) {
-                ClassNode thisType = controller.getThisType();
-                if (isTrait(thisType.getOuterClass())) thisType = 
ClassHelper.dynamicType(); // GROOVY-7242
-
-                fixedReceiver = varX("thisObject", thisType);
-                // account for multiple levels of inner types
-                while (thisType.getOuterClass() != null && 
!target.getDeclaringClass().equals(thisType)) {
-                    FieldNode thisField = thisType.getField("this$0");
-                    thisType = thisType.getOuterClass();
-                    if (thisField != null) {
-                        fixedReceiver = propX(fixedReceiver, "this$0");
-                        fixedReceiver.setType(thisType);
-                        fixedImplicitThis = false;
-                    }
-                }
+                fixedReceiver = thisObjectExpression(classNode, 
target.getDeclaringClass());
+                if (!(fixedReceiver instanceof VariableExpression)) 
fixedImplicitThis = false;
             }
         }
         if (receiver != null && !isSuperExpression(receiver) && 
!isClassWithSuper(receiver)) {
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 67c6cdaa0d..985e640108 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -476,7 +476,7 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter {
         }
         // check outer class
         if (implicitThis && receiverType instanceof InnerClassNode && 
!receiverType.isStaticClass()) {
-            if (makeGetPropertyWithGetter(receiver,  
receiverType.getOuterClass(), propertyName,  safe, implicitThis)) {
+            if (makeGetPropertyWithGetter(receiver, 
receiverType.getOuterClass(), propertyName, safe, implicitThis)) {
                 return true;
             }
         }
@@ -524,8 +524,8 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter {
                     }
                     mv.visitLabel(skip);
                 }
+                operandStack.replace(resultType);
             }
-            operandStack.replace(resultType);
             return true;
         }
         return false;
diff --git a/src/spec/test/builder/ObjectGraphBuilderTest.groovy 
b/src/spec/test/builder/ObjectGraphBuilderTest.groovy
index 7191f94051..27028e440c 100644
--- a/src/spec/test/builder/ObjectGraphBuilderTest.groovy
+++ b/src/spec/test/builder/ObjectGraphBuilderTest.groovy
@@ -22,11 +22,11 @@ import asciidoctor.Utils
 import groovy.test.GroovyTestCase
 
 /**
-* Tests for ObjectGraphBuilder. The tests directly in this file are specific
-* to ObjectGraphBuilder. Functionality in common with other Builders
-* is tested in the parent class.
-*/
-class ObjectGraphBuilderTest  extends GroovyTestCase {
+ * Tests for ObjectGraphBuilder. The tests directly in this file are specific
+ * to ObjectGraphBuilder. Functionality in common with other Builders
+ * is tested in the parent class.
+ */
+final class ObjectGraphBuilderTest extends GroovyTestCase {
 
     void testBuilder() {
         assertScript '''// tag::domain_classes[]
@@ -78,7 +78,6 @@ assert employee.address instanceof Address
 '''
     }
 
-
     void testBuildImmutableFailure() {
         def err = shouldFail '''
 package com.acme
@@ -133,12 +132,12 @@ builder.newInstanceResolver = { Class klazz, Map 
attributes ->
 }
 // end::newinstanceresolver[]
 def person = builder.person(name:'Jon', age:17)
-
         '''
     }
 
     void testId() {
-        assertScript '''package com.acme
+        assertScript '''
+package com.acme
 
 class Company {
     String name
@@ -179,6 +178,6 @@ assert e1.name == 'Duke'
 assert e2.name == 'John'
 assert e1.address.line1 == '123 Groovy Rd'
 assert e2.address.line1 == '123 Groovy Rd'
-'''
+        '''
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/bugs/Groovy8446.groovy 
b/src/test/groovy/bugs/Groovy8446.groovy
index 44a78c5a7f..ec9dd3359f 100644
--- a/src/test/groovy/bugs/Groovy8446.groovy
+++ b/src/test/groovy/bugs/Groovy8446.groovy
@@ -18,19 +18,16 @@
  */
 package groovy.bugs
 
-import groovy.transform.CompileStatic
 import org.junit.Test
 
+import static groovy.test.GroovyAssert.assertScript
 import static groovy.test.GroovyAssert.shouldFail
 
-@CompileStatic
 final class Groovy8446 {
 
-    private GroovyShell shell = new GroovyShell()
-
     @Test
     void testVoidArray0() {
-        shell.evaluate '''
+        assertScript '''
             class C {
                 Void[] m() {}
             }
@@ -40,25 +37,21 @@ final class Groovy8446 {
 
     @Test
     void testVoidArray1() {
-        def err = shouldFail {
-            shell.evaluate '''
-                class C {
-                    void[] m() {}
-                }
-            '''
-        }
-        assert err =~ /void\[\] is an invalid type/ || err =~ /Unexpected 
input: '\('/
+        def err = shouldFail '''
+            class C {
+                void[] m() {}
+            }
+        '''
+        assert err =~ /void\[\] is an invalid type|Unexpected input: '\('/
     }
 
     @Test
     void testVoidArray2() {
-        def err = shouldFail {
-            shell.evaluate '''
-                class C {
-                    def meth(void... args) {}
-                }
-            '''
-        }
+        def err = shouldFail '''
+            class C {
+                def meth(void... args) {}
+            }
+        '''
         assert err =~ /void\[\] is an invalid type|void is not allowed here/
     }
 }
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy 
b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index a7893321c9..3d394de6b7 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -628,30 +628,28 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
     void testRecurseClosureCallAsMethod() {
         assertScript '''
             Closure<Integer> cl
-            cl = { int x -> x == 0 ? x : 1+cl(x-1) }
+            cl = { int x -> x == 0 ? x : 1 + cl(x-1) }
         '''
     }
 
     void testFibClosureCallAsMethod() {
         assertScript '''
             Closure<Integer> fib
-            fib = { int x-> x<1?x:fib(x-1)+fib(x-2) }
-            fib(2)
+            fib = { int x -> x<2 ? x : fib(x-1) + fib(x-2) }
+            assert fib(2) == 1
         '''
     }
 
     void testFibClosureCallAsMethodFromWithinClass() {
         assertScript '''
-            class FibUtil {
-                private Closure<Integer> fibo
-                FibUtil() {
-                    fibo = { int x-> x<1?x:fibo(x-1)+fibo(x-2) }
+            class Fibonacci {
+                private static final Closure<Integer> f
+                static {
+                    f = { int x -> x<2 ? x : f(x-1) + f(x-2) }
                 }
-
-                int fib(int n) { fibo(n) }
+                static int of(int n) { f(n) }
             }
-            FibUtil fib = new FibUtil()
-            fib.fib(2)
+            assert Fibonacci.of(2) == 1
         '''
     }
 

Reply via email to