You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Frédéric Chuong (Jira)" <ji...@apache.org> on 2020/10/07 00:35:00 UTC
[jira] [Created] (GROOVY-9771) STC: "putAt" shortcut notation to
outer class private field from Closure leads to GroovyCastException
Frédéric Chuong created GROOVY-9771:
---------------------------------------
Summary: 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)
Gradle 6.6.1
JUnit 5.7.0
ASM 9.0
Reporter: Frédéric Chuong
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)