codeconsole opened a new pull request, #3135:
URL: https://github.com/apache/groovy/pull/3135
Under `@CompileStatic`, a closure or lambda in trait code that reads a super
trait's static accessor or static property as a property calls the super trait
interface's static forwarder. The forwarder 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 { private static int count = 1; static int getCnt() { count } }
@groovy.transform.CompileStatic
trait U extends T { String m() { def c = { -> cnt }; c() } }
class C implements U {}
assert new C().m() == '1' // MissingMethodException: No signature of static
method: T__count$get for class: T
```
Writing the property in a closure (`cnt = n`, `cnt++`, `s = 'y'`) is
rejected under `@TypeChecked` and `@CompileStatic` with "Cannot set read-only
property". Dynamic Groovy and the method form `getCnt()` work.
A name like this inside a closure is left unchanged by the trait
transformation (GROOVY-8049, GROOVY-9386), so that the closure's delegate can
still provide it. That is kept.
- **Closures:** when the type checker resolves the name to a static method
of a trait through the closure's owner, `StaticInvocationWriter` now calls the
trait helper (the GROOVY-12590 path). It passes the class of the closure's
`thisObject`, which the trait transformation sets to `$self`, or `$static$self`
in a static trait method.
- **Lambdas:** a lambda has no delegate or `thisObject`, so
`TraitReceiverTransformer` rewrites the name to `$self.name` or
`$static$self.name` there, as for a property of the trait itself, and the
lambda captures it.
- **Setters:** in trait code, `StaticTypeCheckingVisitor` now also finds the
static setters of a super trait, since a static interface method is not
inherited by the receiver type.
`p.with { cnt }` still reads `p.cnt` when `p` has the property. This PR is
stacked on #3115 (GROOVY-12590).
## Tests
`TraitASTTransformationTest.testSuperTraitStaticAccessorAsPropertyInClosure`
runs dynamic, `@TypeChecked` and `@CompileStatic`. It covers getters, an isser,
setters, `++`, `+=`, nested closures, static and instance methods, a
grand-super trait, static properties, lambdas, per-class state and
delegate-first resolution. The `@TypeChecked` and `@CompileStatic` variants
fail without the change, and each of the three main-code changes is needed for
them to pass. The `groovy.transform.stc`,
`org.codehaus.groovy.classgen.asm.sc`, `org.codehaus.groovy.transform.traitx`,
`gls`, `groovy.bugs` and `bugs` packages and `groovy.ThisAndSuperTest` pass.
The Checkstyle and CodeNarc gates pass.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]