You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Terence Kent (JIRA)" <ji...@apache.org> on 2015/10/04 03:24:26 UTC

[jira] [Commented] (GROOVY-7597) Static Compiler tries to cast delegate to target type of property accessor

    [ https://issues.apache.org/jira/browse/GROOVY-7597?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14942525#comment-14942525 ] 

Terence Kent commented on GROOVY-7597:
--------------------------------------

We just got hit with this bug moving a project from groovy 2.3.8 to 2.4.5. I think this ought to be a critical issue since it only shows up at runtime and the workarounds are not practical in many cases. 

Searching through Jira, it appears that both GROOVY-7558 and GROOVY-7376 are duplicate reports of this. Since the title of this issue covers the problem very succinctly, I vote for this being the reference issue.

If there is any interest in a unit test being added, I have one and I'm happy to send a pull request.

> Static Compiler tries to cast delegate to target type of property accessor
> --------------------------------------------------------------------------
>
>                 Key: GROOVY-7597
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7597
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation, Static Type Checker
>    Affects Versions: 2.4.3, 2.4.4
>            Reporter: Jason Winnebeck
>            Assignee: Cédric Champeau
>
> I've been able to finally isolate a static compiler issue with accessing properties on delegates that occur within our projects:
> {code}
> class Calculation {
>   boolean isValid() { true }
> }
> class Entity {
>   Calculation getCalculation(String name) { new Calculation() }
> }
> class Feature extends Entity {
> }
> void DoWithFeature(@DelegatesTo(Feature) Closure c) {
>   new Feature().with(c)
> }
> @groovy.transform.CompileStatic
> void doIt() {
>   DoWithFeature() {
>     println getCalculation("whatever").valid
>   }
> }
> doIt()
> {code}
> The result is {{java.lang.ClassCastException: Feature cannot be cast to Calculation}}
> Workarounds:
> * change the property access into a method access "valid" -> "isValid()"
> * Remove CompileStatic annotation
> As seen in the following bytecode, the static compiler tries to cast the delegate to Calculation (which always fails), then tries to call ScriptBytecodeAdapter.castToType to try to cast the "Calculation" back to an Entity to properly call getCalculation("").isValid() on it.
> {code}
>   // access flags 0x1
>   public doCall(Ljava/lang/Object;)Ljava/lang/Object;
>    L0
>     LINENUMBER 19 L0
>     ALOAD 0
>     CHECKCAST script1442861431462$_doIt_closure1
>     INVOKEVIRTUAL script1442861431462$_doIt_closure1.getThisObject ()Ljava/lang/Object;
>     LDC Lgroovy/lang/Script;.class
>     INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
>     CHECKCAST groovy/lang/Script
>     ALOAD 0
>     CHECKCAST script1442861431462$_doIt_closure1
>     INVOKEVIRTUAL script1442861431462$_doIt_closure1.getDelegate ()Ljava/lang/Object;
>     CHECKCAST Calculation
>     LDC LEntity;.class
>     INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
>     CHECKCAST Entity
>     LDC "whatever"
>     INVOKEVIRTUAL Entity.getCalculation (Ljava/lang/String;)LCalculation;
>     INVOKEVIRTUAL Calculation.isValid ()Z
>     INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;
>     INVOKEVIRTUAL groovy/lang/Script.println (Ljava/lang/Object;)V
>     ACONST_NULL
>     ARETURN
>    L1
>     ACONST_NULL
>     ARETURN
>     LOCALVARIABLE this Lscript1442861431462$_doIt_closure1; L0 L1 0
>     LOCALVARIABLE it Ljava/lang/Object; L0 L1 1
>     MAXSTACK = 3
>     MAXLOCALS = 2
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)