You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2020/10/07 01:05:00 UTC

[jira] [Assigned] (GROOVY-9771) STC: "putAt" shortcut notation to outer class private field from Closure leads to GroovyCastException

     [ https://issues.apache.org/jira/browse/GROOVY-9771?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Eric Milles reassigned GROOVY-9771:
-----------------------------------

    Assignee: Eric Milles

> STC: "putAt" shortcut notation to outer class private field from Closure leads to GroovyCastException
> -----------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-9771
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9771
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation
>    Affects Versions: 3.0.6
>         Environment: openjdk version "1.8.0_265"
> OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_265-b01)
> OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.265-b01, mixed mode)
> Groovy 3.0.6
> Gradle 6.6.1
> JUnit 5.7.0
> ASM 9.0
>            Reporter: Frédéric Chuong
>            Assignee: Eric Milles
>            Priority: Major
>
> Given the following usage of the "putAt" shortcut notation to alter an outer class private field:
> {code:Groovy}
> import groovy.transform.CompileStatic
> import org.junit.jupiter.api.Test
> import org.objectweb.asm.ClassReader
> import org.objectweb.asm.util.TraceClassVisitor
> @CompileStatic
> class Bar {
>     private Map<String, Boolean> map = [:]
>     @Test
>     void test() {
>         { ->
>             // troubleshooting only
>             printClass(new Exception().stackTrace[0].className)
>             map['foo'] = true // line 16
>         }.call()
>     }
>     static void printClass(String className) {
>         new ClassReader(className).accept(new TraceClassVisitor(new PrintWriter(System.err)), ClassReader.EXPAND_FRAMES)
>     }
> }
> {code}
> With Groovy 3.0.6, execution leads to the following error:
> {noformat}
> org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Bar$_test_closure1@2a65fe7c' with class 'Bar$_test_closure1' to class 'Bar'
> 	at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:415)
> 	at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:329)
> 	at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:243)
> 	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:615)
> 	at Bar$_test_closure1.doCall(Bar.groovy:16)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 	at java.lang.reflect.Method.invoke(Method.java:498)
> 	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
> 	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
> 	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
> 	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034)
> 	at groovy.lang.Closure.call(Closure.java:412)
> 	at groovy.lang.Closure.call(Closure.java:406)
> 	at Bar.test(Bar.groovy:12)
> {noformat}
> This does not fail with Groovy 3.0.5.
> The bytecode for line 16 is different between 3.0.5 and 3.0.6:
> {panel:title=Groovy 3.0.6|borderColor=red}
> {noformat}
>    L1
>     LINENUMBER 16 L1
>     ICONST_1
>     ISTORE 1
>     LDC LBar$_test_closure1;.class
>     ALOAD 0
>     LDC LBar;.class
>     INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
>     CHECKCAST Bar
>     INVOKESTATIC Bar.pfaccess$0 (LBar;)Ljava/util/Map;
>     LDC "putAt"
>     CHECKCAST java/lang/String
>     ICONST_2
>     ANEWARRAY java/lang/Object
>     DUP
>     ICONST_0
>     LDC "foo"
>     AASTORE
>     DUP
>     ICONST_1
>     ILOAD 1
>     INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;
>     AASTORE
>     INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.invokeMethodN (Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
>     POP
>     ILOAD 1
>     INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;
>     ARETURN
> {noformat}
> {panel}
> {panel:title=Groovy 3.0.5, no error|borderColor=green}
> {noformat}
>    L1
>     LINENUMBER 16 L1
>     ICONST_1
>     ISTORE 1
>     ALOAD 0
>     LDC "map"
>     INVOKEINTERFACE groovy/lang/GroovyObject.getProperty (Ljava/lang/String;)Ljava/lang/Object; (itf)
>     LDC "foo"
>     ILOAD 1
>     INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;
>     INVOKESTATIC org/codehaus/groovy/runtime/DefaultGroovyMethods.putAt (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V
>     ACONST_NULL
>     POP
>     ILOAD 1
>     INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;
>     ARETURN
> {noformat}
> {panel}
> There was a previously fixed issue, [GROOVY-9385] fixed in 3.0.1, having similar conditions (\@CompileStatic, closure, private member), I'm not sure whether it's related.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)