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

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

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

   Under `@CompileStatic`, a call from trait code to a `@Virtual` static method 
whose name matches a `java.lang.Class` method binds to the `Class` method:
   
   ```groovy
   import groovy.transform.Virtual
   @groovy.transform.CompileStatic
   trait T {
       @Virtual static String getName() { 'trait' }
       static String sm() { getName() }
   }
   class C implements T { static String getName() { 'impl' } }
   class D implements T {}
   assert C.sm() == 'impl'   // 'C'
   assert D.sm() == 'trait'  // 'D'
   ```
   
   The same happens for `getSimpleName`, `isInterface`, `getModifiers` and DGM 
methods such as `dump()`. A `@Virtual static Object cast(Object)` fails with a 
`ClassCastException`, because the call takes `Class<C>.cast`'s return type. It 
also happens for calls from instance trait methods and for a `@Virtual` static 
of a super trait, and in 6.0.0. Dynamic Groovy and `@TypeChecked` run the 
implementing class's method.
   
   The trait transformation rewrites the call to `$static$self.getName()` (or 
`((Class) $self.getClass()).getName()`) and marks it for dynamic dispatch. 
`TraitTypeCheckingExtension.handleMissingMethod` honours that mark only when no 
method is found, and here the type checker finds `Class.getName()` on the 
`Class<T>` receiver.
   
   `TraitTypeCheckingExtension.onMethodSelection` now makes a call carrying 
that mark dynamic even when a method was selected, with the return type of the 
`@Virtual` method. The type checker treats the replaced target as an extension 
intervention, so static compilation emits a dynamic call through the 
implementing class.
   
   The property form (`name` for `@Virtual static String getName()`) is handled 
with #3121 (GROOVY-12594), which adds property-syntax support for `@Virtual` 
static accessors.
   
   ## Tests
   
   `VirtualAnnotationTest.virtualStatic_namedLikeClassMethod` and 
`virtualStatic_ofSuperTrait_namedLikeClassMethod` run dynamic, `@TypeChecked` 
and `@CompileStatic`. Their `@CompileStatic` variants fail without the change. 
The `groovy.transform.stc`, `org.codehaus.groovy.classgen.asm.sc`, 
`org.codehaus.groovy.transform.traitx` and `gls` packages, 
`groovy.ThisAndSuperTest` and `TraitsSpecificationTest` pass. The Checkstyle 
and CodeNarc gates pass.
   




> SC calls the java.lang.Class method instead of a @Virtual trait static method 
> of the same name
> ----------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12601
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12601
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> {code:groovy}
> import groovy.transform.Virtual
> @groovy.transform.CompileStatic
> trait T {
>     @Virtual static String getName() { 'trait' }
>     static String sm() { getName() }
> }
> class C implements T { static String getName() { 'impl' } }
> class D implements T {}
> assert C.sm() == 'impl'
> assert D.sm() == 'trait'
> {code}
> Actual: {{C.sm()}} returns {{'C'}} and {{D.sm()}} returns {{'D'}}. The trait 
> calls {{Class.getName()}}. The same happens for other {{Class}} and DGM names 
> such as {{getSimpleName}}, {{isInterface}}, {{getModifiers}} and {{dump}}. A 
> {{@Virtual static Object cast(Object)}} fails with a {{ClassCastException}}. 
> It also happens from instance trait methods and for a {{@Virtual}} static of 
> a super trait.
> Expected: {{'impl'}} and {{'trait'}}, as dynamic Groovy and {{@TypeChecked}} 
> give.
> The trait transformation rewrites the call to a call on the static self (a 
> Class) and marks it for dynamic dispatch. Static type checking finds 
> {{Class.getName()}} on that receiver, so the trait type checking extension is 
> never asked and static compilation binds the call to the {{Class}} method.
> 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