[
https://issues.apache.org/jira/browse/GROOVY-12512?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18133806#comment-18133806
]
Paul King commented on GROOVY-12512:
------------------------------------
The fix (master 4d2d9c21d6 + 37b3c2a3a6, 6.0.x 1e7cd0efdb + 83e4a4b66f) ended
up a little broader than the description, and the message differs from the one
suggested:
*Unqualified call* ({{pm()}}) from an anonymous class with no enclosing
instance: the type checker now treats such a class like a static nested class
when looking up outer-class members, so both {{@TypeChecked}} and
{{@CompileStatic}} report a compile error:
{noformat}
Cannot find matching method Box$1#pm()
{noformat}
That is the message a static nested class already gets, rather than the
lambda-style "Non-static method ... cannot be called from static context". This
covers every case in the description: static method, static initializer, static
field initializer, a closure inside the anonymous class, an anonymous class
inside a closure, nested anonymous classes, a private method, and a static
method of a static nested class. Dynamic Groovy is unchanged: the call still
throws MissingMethodException at run time.
*Qualified call* ({{Box.this.pm()}}): this was not in the description, but it
failed with VerifyError in every mode, including dynamic Groovy. That happened
in such an anonymous class and also in any static nested class, which never has
an enclosing instance. It is now a compile error in every mode:
{noformat}
The usage of 'Class.this' and 'Class.super' is not allowed in 'Box$1', which
has no enclosing instance of 'Box'.
{noformat}
*Argument of this(...) or super(...)*: an anonymous class created there has no
enclosing instance either, because the instance is not built yet. It previously
got the constructor's non-static scope, so under {{@CompileStatic}} {{pm()}}
and an instance field compiled and failed with VerifyError, and
{{Box.this.pm()}} failed in every mode. VariableScopeVisitor now gives it a
static scope, so it is checked like an anonymous class in a static method:
{{pm()}} gets "Cannot find matching method", an instance field gets "Apparent
variable 'id' was found in a static scope ...", and {{Box.this}} gets the error
above. Its own members, the constructor's parameters and static members of the
outer class can still be used.
An anonymous class created in an instance context, including one nested inside
another, still sees the outer instance as before.
> SC: instance method of the enclosing class called from an anonymous class in
> a static context compiles, then fails with VerifyError
> -----------------------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12512
> URL: https://issues.apache.org/jira/browse/GROOVY-12512
> Project: Groovy
> Issue Type: Bug
> Components: Static compilation, Static Type Checker
> Affects Versions: 6.0.0
> Reporter: Scott Murphy Heiberg
> Assignee: Paul King
> Priority: Major
> Fix For: 7.0.0-alpha-1, 6.0.1
>
>
> An anonymous class created in a static method has no enclosing instance, so
> it cannot call an instance method of the enclosing class. {{@CompileStatic}}
> accepts the call and generates code that fails verification:
> {code:groovy}
> @groovy.transform.CompileStatic
> class Box {
> String pm() { 'pm' }
> static Object test() {
> def result
> new Runnable() {
> void run() { result = pm() }
> }.run()
> result
> }
> }
> Box.test()
> {code}
> Result:
> * {{@CompileStatic}}: {{java.lang.VerifyError: Bad type on operand stack}}
> (in {{Box$1.run}})
> * dynamic Groovy and {{@TypeChecked}}:
> {{groovy.lang.MissingMethodException}}: "No signature of method: pm for
> class: Box$1 is applicable for argument types: ()"
> * javac: "non-static method pm() cannot be referenced from a static context"
> The same happens for a private method, for an anonymous class in a static
> initializer or a static field initializer, and for an anonymous class in a
> static method of a static nested class (all {{VerifyError}}). With a closure
> inside the anonymous class, or an anonymous class created inside a closure in
> a static method, {{@CompileStatic}} fails at run time with a
> {{ClassCastException}} ({{Box$1 cannot be cast to Box}}, or {{java.lang.Class
> cannot be cast to Box}}).
> A reference to an instance field in the same place is already rejected
> ("Apparent variable 'id' was found in a static scope but doesn't refer to a
> local variable, static field or class"), and the same call in a lambda gets
> "Non-static method Box#pm cannot be called from static context".
> Seen in 4.0.33, 5.0.8, 6.0.0 and master.
> Expected: a compile error under {{@TypeChecked}} and {{@CompileStatic}}, such
> as "Non-static method Box#pm cannot be called from static context".
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)