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

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

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

   Under `@CompileStatic`, `toString()`, `hashCode()`, `equals()` and 
`getClass()` called without a receiver inside a closure or lambda now go to the 
delegate or the owner according to the resolve strategy, as they do in dynamic 
and `@TypeChecked` code and as they did in 4.0. So `new StringBuilder().with { 
append('w'); toString() }` returns `'w'`, not the closure's `toString()`. In a 
lambda, `toString()` is the enclosing instance's, as in Java. In a static 
method it is the class's. Methods that `Closure` declares, such as 
`getDelegate()` or `getMetaClass()`, still resolve against the closure.
   
   The type checker looked up the methods of `Closure` before the delegate and 
the owner, and that lookup also returned the methods `Closure` inherits from 
`Object`. It now leaves those out, and the static invocation writer calls a 
method of `Object` that was resolved against the owner on the closure's this 
object, as it already did for other owner methods.
   
   A closure returned by `dehydrate()` has no this object. If it calls one of 
these methods without a receiver, it uses its own method, as before; the writer 
loads the this object and falls back to the closure when it is `null`.
   
   Tests: `ClosuresSTCTest.testClosureObjectMethodPrecedence` (also run 
statically compiled by `ClosuresStaticCompileTest`) and 
`ClosuresStaticCompileTest.testObjectMethodsInClosureWithoutThisObject`, which 
fail without the change. The `groovy`, `gls`, `bugs` and `org.codehaus.groovy` 
packages pass (15,513 tests), apart from `bugs.Groovy12363`, which also fails 
on master when it runs after `bugs.Groovy12142` in the same JVM (GROOVY-12580 
fixes it). The Checkstyle and CodeNarc gates pass.
   
   A regression in 5.0.0: 4.0.33 is correct, 5.0.8 and 6.0.0 are not.
   




> 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
>            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.



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

Reply via email to