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]

Reply via email to