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

ASF GitHub Bot commented on GROOVY-12618:
-----------------------------------------

codeconsole opened a new pull request, #3144:
URL: https://github.com/apache/groovy/pull/3144

   An implicit-this call from a closure in trait code to a public static method 
inherited from a super trait always called the super trait's method. The 
closure's delegate was never consulted:
   
   ```groovy
   trait T { static int size() { 1 } }
   trait U extends T { def m() { [5, 6].with { size() } } }
   class C implements U {}
   assert new C().m() == 2   // was 1; the same code with classes gives 2
   ```
   
   5.0.8 and 6.0.0 behave the same, in dynamic, `@TypeChecked` and 
`@CompileStatic` code. This PR is stacked on #3138 (GROOVY-12611), which made 
this work for private and static methods declared by the trait itself.
   
   - `TraitReceiverTransformer` now attaches the plain implicit-this call to 
calls to super trait static methods too. #3138 excluded them by checking that 
the trait declares the method.
   - The type checker then selects the delegate the same way it does for the 
trait's own methods. Statically compiled code otherwise keeps the helper call.
   - In dynamically compiled code, `ClosureMetaClass` falls back to the public 
static method of a super trait helper when the trait helper does not declare 
the method. It searches the super traits in the order the trait helper's 
`$static_methodMissing` forwards to them. Without that fallback the closure 
would reach the static method copied into the implementing class, so an 
implementing class that declares its own static method of that name would be 
called, while trait code outside closures calls the super trait's method.
   
   ## Tests
   
   
`TraitASTTransformationTest.testSuperTraitStaticMethodInDelegateFirstClosure` 
and `testSuperTraitStaticMethodInClosureWithDelegateSetAtRuntime` fail without 
the change, in dynamic, `@TypeChecked` and `@CompileStatic` modes. 
`org.codehaus.groovy.transform.traitx`, `groovy.transform.stc`, 
`org.codehaus.groovy.classgen.asm.sc`, `gls.closures`, 
`org.codehaus.groovy.runtime.metaclass`, `groovy.Closure*` and 
`groovy.ThisAndSuperTest` pass. The Checkstyle and CodeNarc gates pass.
   




> A public static super trait method called from a closure in trait code 
> ignores the closure's delegate
> -----------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12618
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12618
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 5.0.8, 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> {code:groovy}
> trait T { static int size() { 1 } }
> trait U extends T {
>     def m() { [5, 6].with { size() } }
>     static sm() { [5, 6].with { size() } }
> }
> class C implements U {}
> assert new C().m() == 2
> assert C.sm() == 2
> {code}
> Actual: both calls return 1, in dynamic, @TypeChecked and @CompileStatic code.
> Expected: 2, as with the same code written with classes. Inside a with 
> closure, the list delegate's size() comes before the owner's.
> The trait transformation rewrites an implicit-this call to a public static 
> method inherited from a super trait into a direct call on the trait helper 
> class, so the closure's delegate is never consulted. GROOVY-12611 changes 
> this for private and static methods declared by the trait itself, but not for 
> methods inherited from a super trait.
> Seen in 5.0.8 and 6.0.0.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to