You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (JIRA)" <ji...@apache.org> on 2019/05/01 13:37:00 UTC
[jira] [Resolved] (GROOVY-9086) @CompileStatic of closure calls
with OWNER_FIRST fail at runtime with ClassCastException
[ https://issues.apache.org/jira/browse/GROOVY-9086?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Paul King resolved GROOVY-9086.
-------------------------------
Resolution: Fixed
Assignee: Paul King
Fix Version/s: 2.5.7
3.0.0-beta-1
> @CompileStatic of closure calls with OWNER_FIRST fail at runtime with ClassCastException
> ----------------------------------------------------------------------------------------
>
> Key: GROOVY-9086
> URL: https://issues.apache.org/jira/browse/GROOVY-9086
> Project: Groovy
> Issue Type: Bug
> Components: Static compilation
> Affects Versions: 2.5.6
> Environment: WIndows7, Groovy 2.5.6, Java 8 + 11
> Reporter: Andreas Turban
> Assignee: Paul King
> Priority: Major
> Fix For: 3.0.0-beta-1, 2.5.7
>
> Attachments: StaticTypeCheckingVisitor.java, TestScript.groovy
>
> Time Spent: 0.5h
> Remaining Estimate: 0h
>
> The attached script fails with a ClassCastException, when method m2 is annotated with
>
> {code:java}
> strategy = Closure.OWNER_FIRST
> {code}
> but work with
>
> {code:java}
> strategy = Closure.DELEGATE_FIRST
> {code}
> The expected system-out should be
>
> {code:java}
> c1Method called{code}
> in both cases. The generated bytecode for closure Test$_test_closure1$_closure2.class contains a call to getDelegate() instead of getOwner() in case of Closure.OWNER_FIRST. But correctly generates code getOwner() in case of Closure.DELEGATE_FIRST.
> The resulting ClassCastException at runtime is:
> {code:java}
> java.lang.ClassCastException: Test$C2 cannot be cast to groovy.lang.Closure
> at Test$_test_closure1$_closure2.doCall(TestScript.groovy:28)
> at Test$_test_closure1$_closure2.doCall(TestScript.groovy)
> at Test.m2(TestScript.groovy:20)
> at Test$_test_closure1.doCall(TestScript.groovy:26)
> at Test$_test_closure1.doCall(TestScript.groovy)
> at Test.m1(TestScript.groovy:8)
> at Test.test(TestScript.groovy:25)
> at Test$test.call(Unknown Source)
> at TestScript.run(TestScript.groovy:42)
> {code}
> The wrong bytecode for case Closure.OWNER_FIRST:
> {code:java}
> public java.lang.Object doCall(java.lang.Object);
> descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
> flags: ACC_PUBLIC
> Code:
> stack=1, locals=2, args_size=2
> 0: aload_0
> 1: checkcast #2 // class Test$_test_closure1$_closure2
> 4: invokevirtual #29 // Method getDelegate:()Ljava/lang/Object;
> 7: checkcast #4 // class groovy/lang/Closure
> 10: invokevirtual #30 // Method groovy/lang/Closure.getDelegate:()Ljava/lang/Object;
> 13: checkcast #32 // class Test$C1
> 16: invokevirtual #36 // Method Test$C1.c1Method:()V
> 19: aconst_null
> 20: areturn
> {code}
> The correct bytecode for case Closure.DELEGATE_FIRST:
> {code:java}
> public java.lang.Object doCall(java.lang.Object);
> descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
> flags: ACC_PUBLIC
> Code:
> stack=1, locals=2, args_size=2
> 0: aload_0
> 1: checkcast #2 // class Test$_test_closure1$_closure2
> 4: invokevirtual #29 // Method getOwner:()Ljava/lang/Object;
> 7: checkcast #4 // class groovy/lang/Closure
> 10: invokevirtual #32 // Method groovy/lang/Closure.getDelegate:()Ljava/lang/Object;
> 13: checkcast #34 // class Test$C1
> 16: invokevirtual #38 // Method Test$C1.c1Method:()V
> 19: aconst_null
> 20: areturn
> {code}
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)