codeconsole opened a new pull request, #3129:
URL: https://github.com/apache/groovy/pull/3129
Under `@CompileStatic`, a lambda in a trait method that calls an instance
method of the trait by implicit `this` fails at run time:
```groovy
import java.util.function.Supplier
@groovy.transform.CompileStatic
trait U {
String getUname() { 'u' }
String a() { Supplier<String> s = () -> getUname(); s.get() }
}
class C implements U {}
assert new C().a() == 'u' // ClassCastException: class java.lang.Class
cannot be cast to class U
```
The same happens for a super trait's accessor (`uname` or `getUname()`), a
lambda in a lambda, a closure in a lambda and a lambda in a trait field
initializer, and in 4.0.33, 5.0.8 and 6.0.0. Dynamic Groovy, `@TypeChecked` and
closures work.
A trait method body becomes a static method of `T$Trait$Helper` that takes
the instance as `$self`. A closure there is rewritten to
`closure.rehydrate($self,$self,$self)`. Since GROOVY-11265 static compilation
drops that rewrite for a native lambda, and `StaticTypesLambdaWriter` then
passes the helper class as the lambda's owner and this object, because the
enclosing method is static. The implicit-this call reads `getThisObject()` and
casts it to the trait.
`StaticTypesLambdaWriter.loadLambdaReceiver` now passes the enclosing helper
method's `$self` as the owner and this object of a lambda that accesses
instance members, as `rehydrate` does for a closure. Closures nested in such a
lambda take its this object, so they work too. Static trait methods are
unchanged. Doing this in `TraitReceiverTransformer` instead would break a
lambda coerced to `Closure` that resolves names through a delegate (for example
`obj.with((b) -> prop)`): that transform runs before type checking and cannot
tell the two kinds of lambda apart.
## Tests
`TraitWithClosureOrLambda` gets five tests.
`testInvokeTraitMethodFromTraitLambda`,
`testInvokeSuperTraitMethodFromTraitLambda`,
`testInvokeTraitMethodFromTraitLambdaInFieldInitializer` and
`testInvokeTraitMethodFromTraitLambdaOrClosure` fail without the change.
`testInvokeTraitStaticOrPrivateMethodFromTraitLambda` covers neighbouring
shapes. `groovy.transform.stc.*`, `org.codehaus.groovy.classgen.asm.sc.*`,
`org.codehaus.groovy.transform.traitx.*` 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]