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

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

paulk-asert commented on PR #3102:
URL: https://github.com/apache/groovy/pull/3102#issuecomment-6535519149

   Thanks, this looks good overall. Two things before merge:
   
   **1. Closures using `TO_SELF` no longer compile.** A closure whose resolve 
strategy is `TO_SELF` can't call `toString()` any more:
   
       class C {
           String toString() { 'C' }
           static Object run(@DelegatesTo(value=String, 
strategy=Closure.TO_SELF) Closure c) {
               c.resolveStrategy = Closure.TO_SELF; c.delegate = 'd'; c()
           }
           Object m() { run { -> toString() } }
       }
   
   On master it compiles, and both dynamic and `@CompileStatic` return the 
closure's own `toString()`. With this PR, both `@CompileStatic` and 
`@TypeChecked` fail with `[Static type checking] - Cannot find matching method 
C#toString()`. With `TO_SELF` only the closure itself is searched, and its 
`Object` methods have now been removed from that search. Could the `removeIf` 
be skipped when the strategy is `TO_SELF`? A test for it would be good too.
   
   **2. The 4.0 claim in the description.** Results for `toString()` called 
inside a closure:
   
   | | 4.0.32 | 5.0.6 | master | this PR |
   |---|---|---|---|---|
   | dynamic | closure | closure | owner | owner |
   | `@CompileStatic` | owner | closure | closure | owner |
   
   Dynamic code only started going to the delegate or owner with GROOVY-11858, 
which is on master and 6.0.x but not on 5.1.x. So in 4.0, SC and dynamic 
disagreed, and in 5.x they agree. This PR lines SC up with 6.0+ dynamic 
behaviour.
   
   For that reason I'd backport to 6.0.x (with the `TO_SELF` fix) but not to 
5.1.x. On 5.1.x, the `@TypeChecked` variant of 
`testClosureObjectMethodPrecedence` fails, because it runs dynamically, while 
the statically compiled one passes. Backporting would split SC from dynamic 
there.
   
   Minor and optional: with `rehydrate(null, owner, null)`, dynamic code calls 
the owner's method, while this PR falls back to the closure. Trying 
`getOwner()` before the closure would match dynamic in that case. Not a blocker.




> SC: toString(), hashCode(), equals() and getClass() in a closure ignore the 
> delegate and the owner
> --------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12576
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12576
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation
>    Affects Versions: 5.0.8, 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Assignee: Daniel Sun
>            Priority: Major
>
> Under {{@CompileStatic}}, an implicit-this call to a method of {{Object}} in 
> a closure or lambda is made on the closure itself:
> {code:groovy}
> @groovy.transform.CompileStatic
> class C {
>     String m() { new StringBuilder().with { append('w'); toString() } }
> }
> assert new C().m() == 'w' // C$_m_closure1@1b2c3d4
> {code}
> 4.0.33 returns {{'w'}}. The type checker looks up the methods of {{Closure}} 
> before the delegate and the owner, and that lookup also returns the methods 
> {{Closure}} inherits from {{Object}}. With {{with}}, {{tap}}, {{identity}} or 
> a {{@DelegatesTo(strategy = DELEGATE_FIRST)}} method this ignores the 
> delegate; in a plain closure it ignores the owner, and in a lambda the 
> enclosing instance, which Java and dynamic Groovy both use. This happens in 
> methods, constructors, field initializers and static initializers.
> Dynamic Groovy tries the closure first only for methods that {{Closure}} or 
> {{GroovyObject}} declare; a method the closure inherits from elsewhere goes 
> to the delegate or the owner according to the resolve strategy. Expected: the 
> same under static compilation. Methods declared by {{Closure}}, such as 
> {{getDelegate()}}, still resolve against the closure, and a closure without a 
> this object (from {{dehydrate()}}) uses its own method.
> PR: https://github.com/apache/groovy/pull/3102



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

Reply via email to