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

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

codeconsole commented on PR #3092:
URL: https://github.com/apache/groovy/pull/3092#issuecomment-6526975263

   @daniellansun thanks.
   
   1. Merged `master` (9ec3b8638b), so the branch has #3094 / GROOVY-12565.
   
   2. Dynamic code changes only where it called the helper class. I compared 51 
dynamic (non-SC, non-TC) scripts on `master` and on this branch, in instance 
and static trait methods: `this.m()`, `this.prop`, `this` passed out, 
`toString()`/`getClass()`, overrides, abstract and `@SelfType` methods, 
delegate strategies, user `rehydrate` and nested closures. The 29 that `master` 
got right give the same result (implicit calls, `this` alone or passed out, 
`this.prop` reads and writes, delegate strategies where an explicit `this` 
still ignores the delegate, rehydrated closures). In the other 22, `master` 
sent the call to `T$Trait$Helper`: a MissingMethodException for a method with 
arguments, an abstract, `@SelfType` or implementor-only method; the helper's 
`toString()`, `getClass()` and `getSimpleName()`; and `this.over()` running the 
trait's `over` with a null `$self`, skipping the implementing class's override 
that implicit `over()` runs. `testExplicitThisMethodCallInTraitClosure` and 
`testStaticClosureFieldCalledAsMethod` already run without SC; 50e5fa32ac adds 
the dynamic-only `testExplicitThisInDynamicTraitClosure` (overrides, nested 
closures, a delegate-first closure, static methods), which fails on `master`. 
The description says so now.
   
   3. GROOVY-10932 is still open, with nothing for it on `master`. The recent 
trait work on `master` meets this PR only in 
`TraitReceiverTransformer.transformMethodCallOnThis`, and they do not touch: 
the `@Virtual` dispatch (GROOVY-11985/12093) runs only outside a closure, and 
this PR changes only the fall-through inside one. The merge had no conflicts, 
and `Groovy11985`, `TraitStaticDispatchMatrix` and the rest of `traitx` pass. 
For precompiled traits the helper ABI is unchanged: `javap` of the trait 
interface, `$Trait$Helper`, `$Trait$FieldHelper`, `$Trait$StaticFieldHelper` 
and the lambda classes gives identical signatures from both compilers; only the 
helper's own closure classes differ (a captured `$self`, a narrower `doCall` 
return type), and only the helper creates them. An SC `@SelfType` trait and a 
dynamic trait compiled by each compiler, used by an `@CompileStatic` class 
compiled by each, link and run in all four combinations.
   
   4. `isStaticPropertyOfTraitSelf` is reached only for a property the type 
checker typed as `Closure` and is calling as a method. A closure property never 
has an isser (`static Closure isH()` does not define a property `h`, so `h()` 
is a compile error under SC and TC), and a `boolean` property cannot be called, 
so 690719d3aa drops the dead `is` lookup and checks `get<Name>`, built with the 
same `BeanUtils.capitalize` that `TraitASTTransformation.processProperty` uses. 
If the lookup missed, the call would take the trait's static accessor as 
before; a false positive would only make the read dynamic on the implementing 
class, which returns the right value. 
`testStaticBooleanPropertyAndExplicitAccessorsInTraitClosure`, under SC, TC and 
dynamic, covers a `static boolean` read through its isser in closures, nested 
closures and lambdas of static and instance trait methods (each implementing 
class keeps its own value), `isFlag()`/`getFlag()`, an explicit `static boolean 
isReady()`, an explicit `static Closure getG()` called as `g()`, a two-letter 
name (`aB()`), and a static closure of a super trait.
   
   83f2ebcc88 also corrects the issue number in the new tests' comments (they 
said GROOVY-12492). The `traitx`, `org.codehaus.groovy.transform`, STC/SC, 
`groovy.bugs`, `bugs`, `gls` and `groovy.lang` packages pass (10,205 tests), as 
do the Checkstyle and CodeNarc gates.
   




> SC: closures and lambdas in a trait method see the trait helper class instead 
> of the trait instance
> ---------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12563
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12563
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation, Static Type Checker
>    Affects Versions: 4.0.33, 5.0.8, 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> In a statically compiled trait method, closures and lambdas get the static 
> helper class where the trait instance (or, in a static method, the 
> implementing class) is expected:
> {code:groovy}
> @groovy.transform.CompileStatic
> trait T {
>     String helper() { 'helper' }
>     Object own() { def c = { owner }; c() }
>     String viaThis() { def c = { this.helper() }; c() }
>     String viaLambda() { java.util.function.Supplier<String> s = () -> 
> helper(); s.get() }
> }
> @groovy.transform.CompileStatic
> class C implements T { }
> new C().own()       // GroovyCastException: Cannot cast object 'C@...' with 
> class 'C' to class 'T$Trait$Helper'
> new C().viaThis()   // ClassCastException: class java.lang.Class cannot be 
> cast to class T$Trait$Helper
> new C().viaLambda() // ClassCastException: class java.lang.Class cannot be 
> cast to class T
> {code}
> Also: {{thisObject}}, {{delegate}} without {{@DelegatesTo}}, {{getOwner()}} 
> and {{getThisObject()}} in such a closure (also under {{@TypeChecked}}); a 
> closure written in a lambda; {{this.m()}} in a closure of a dynamic or 
> {{@TypeChecked}} trait (MissingMethodException for a method with arguments, 
> the helper's {{toString()}} and {{getClass()}}); and calling a static closure 
> field of the trait as a method:
> {code:groovy}
> @groovy.transform.CompileStatic
> trait T {
>     static Closure<String> f = { 'f' }
>     static String callF() { f() }
> }
> @groovy.transform.CompileStatic
> class C implements T { }
> C.callF() // 6.0.0: MissingMethodException: No signature of static method: 
> T__f$get for class: T
>           // 4.0.33, 5.0.8: [Static type checking] - Cannot find matching 
> method java.lang.Class#f()
> {code}
> Expected: these give the values and calls dynamic Groovy gives: the trait 
> instance as this object, owner and delegate of a closure written directly in 
> a trait method, the lambda as the owner of a closure written in a lambda, and 
> the implementing class's static field.
> PR: https://github.com/apache/groovy/pull/3092



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

Reply via email to