[
https://issues.apache.org/jira/browse/GROOVY-12590?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18135474#comment-18135474
]
ASF GitHub Bot commented on GROOVY-12590:
-----------------------------------------
codeconsole opened a new pull request, #3115:
URL: https://github.com/apache/groovy/pull/3115
Under `@CompileStatic`, trait code that uses property syntax for a static
accessor of the trait calls the trait interface's static forwarder, which
passes the trait itself to the trait helper as the receiver class, so an
accessor that reads trait state fails:
```groovy
@groovy.transform.CompileStatic
trait T {
static boolean flag = true
static boolean isReady() { flag }
static String sm() { ready ? 'yes' : 'no' }
}
class C implements T {}
assert C.sm() == 'yes' // MissingMethodException: No signature of static
method: T__flag$get for class: T
```
`@TypeChecked` and dynamic Groovy work, and so does the direct call
`isReady()`, which the trait transformation turns into
`T$Trait$Helper.isReady($static$self)`. The same failure occurs in instance
trait methods, in closures and lambdas, for a static setter written as an
assignment, a compound assignment or `++`/`--`, and for accessors of a super
trait.
`StaticInvocationWriter` now writes a call to a static method of a trait
whose receiver is the trait helper's `$static$self` or `$self` parameter as a
call to the trait helper, passing `$static$self` or `$self.getClass()` as the
receiver class, as the method call form does. `StaticTypesCallSiteWriter` keeps
`$static$self` as the receiver of a static getter instead of replacing it with
the trait class, which the getter half of `cnt++` goes through. An explicit
`T.isReady()` is not changed.
## Tests
`TraitASTTransformationTest.testTraitStaticAccessorReadAsProperty`,
`testTraitStaticAccessorWrittenAsProperty` and
`testSuperTraitStaticAccessorAsProperty` run dynamic, `@TypeChecked` and
`@CompileStatic`; the `@CompileStatic` variant of each fails without the
change. The `groovy.transform.stc`, `org.codehaus.groovy.classgen.asm.sc`,
`org.codehaus.groovy.transform.traitx` and `gls` packages and
`groovy.ThisAndSuperTest` pass. The Checkstyle and CodeNarc gates pass.
Seen in 6.0.0; 5.0.8 and 4.0.33 reject the code at compile time.
> SC calls a trait's static accessor read as a property on the trait instead of
> the implementing class
> ----------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12590
> URL: https://issues.apache.org/jira/browse/GROOVY-12590
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> {code:groovy}
> @groovy.transform.CompileStatic
> trait T {
> static boolean flag = true
> static boolean isReady() { flag }
> static String sm() { ready ? 'yes' : 'no' }
> static Closure getG() { { -> flag } }
> static Object sg() { g.call() }
> }
> class C implements T {}
> assert C.sm() == 'yes'
> assert C.sg() == true
> {code}
> Actual: groovy.lang.MissingMethodException: No signature of static method:
> T__flag$get for class: T is applicable for argument types: () values: []
> Expected: both assertions pass, as they do with @TypeChecked or without an
> annotation, and as they do when the accessor is called directly
> ({{isReady()}}, {{getG()}}).
> The same happens in instance trait methods, in closures and lambdas, and when
> a static accessor is written with property syntax ({{cnt = 1}}, {{cnt += 1}},
> {{cnt++}} for a static {{setCnt(int)}}), including for an accessor of a super
> trait. Under static compilation the property resolves to the static method
> that the trait interface declares, which forwards to the trait helper with
> the trait itself as the receiver class, so the accessor cannot reach the
> implementing class's trait state. The direct method call passes the
> implementing class to the helper instead.
> Seen in 6.0.0 and master. 5.0.8 rejects the code with "No such property:
> ready for Class or static property for class: T", and 4.0.33 with "Access to
> T#ready is forbidden".
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)