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

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

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

   A public trait static is promoted to the trait interface so `T.m()` works. 
If that static calls a `@Virtual` static, the call fails when made through the 
trait:
   
   ```groovy
   import groovy.transform.Virtual
   trait T {
       @Virtual static String setting() { 'default' }
       static String describe() { 'setting=' + setting() }
   }
   class C implements T {}
   assert C.describe() == 'setting=default'
   assert T.describe() == 'setting=default'  // MissingMethodException: No 
signature of static method: setting for class: T
   ```
   
   The interface forwarder calls the helper with the trait interface as 
`$static$self`. The `@Virtual` call site dispatches dynamically on 
`$static$self`, and `@Virtual` statics are deliberately not on the interface. 
This fails in dynamic, `@TypeChecked` and `@CompileStatic` code, including the 
`Configurable.describe()` case of the documented `@Virtual` example, and in 
6.0.0.
   
   `TraitReceiverTransformer` now emits `$static$self.isInterface() ? 
T$Trait$Helper.m($static$self, x) : $static$self.m(x)` for a `@Virtual` call 
from a static trait method. Through the trait, where there is no implementing 
class, the trait's own implementation runs. Through an implementing class, the 
dispatch is unchanged and an override still wins. The arguments are transformed 
once and shared by both branches. For a `@Virtual` static inherited from a 
super trait, the declaring trait's helper is called. Calls from instance 
methods and from closures are unchanged. The traits guide gains a callout for 
the through-the-trait call.
   
   ## Tests
   
   `VirtualAnnotationTest` adds tests for the call through the trait in 
dynamic, `@TypeChecked` and `@CompileStatic` code. They cover a `@Virtual` with 
arguments, an implementing class that overrides it, closure and lambda 
arguments, a sub-trait's promoted static, and a call from a closure. The first 
three fail without the change, as does the extended 
`TraitsSpecificationTest.testVirtualStaticDefault`. 
`org.codehaus.groovy.transform.traitx.*`, `groovy.transform.stc.*`, 
`org.codehaus.groovy.classgen.asm.sc.*`, `groovy.ThisAndSuperTest` and 
`TraitsSpecificationTest` pass. The Checkstyle and CodeNarc gates pass.
   




> A promoted trait static that calls a @Virtual static fails with 
> MissingMethodException when called through the trait
> --------------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12604
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12604
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> {code:groovy}
> import groovy.transform.Virtual
> trait T {
>     @Virtual static String setting() { 'default' }
>     static String describe() { 'setting=' + setting() }
> }
> class C implements T {}
> assert C.describe() == 'setting=default'
> assert T.describe() == 'setting=default'
> {code}
> Actual: {{T.describe()}} throws {{MissingMethodException: No signature of 
> static method: setting for class: T is applicable for argument types: () 
> values: []}}. This happens in dynamic Groovy, with @TypeChecked and with 
> @CompileStatic. The trait documentation's own @Virtual example fails the same 
> way when called as {{Configurable.describe()}}.
> Expected: called through the trait itself there is no implementing class, so 
> the trait's own (default) implementation of the @Virtual static is used, and 
> the call returns {{setting=default}}.
> Public trait statics are promoted to the trait interface, and the forwarder 
> passes the trait interface as the static self. The @Virtual call site 
> dispatches dynamically on that self, but @Virtual statics are deliberately 
> not promoted to the interface, so the call finds nothing.
> Seen in 6.0.0 (the first version with @Virtual).



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

Reply via email to