[
https://issues.apache.org/jira/browse/GROOVY-12479?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18130675#comment-18130675
]
ASF GitHub Bot commented on GROOVY-12479:
-----------------------------------------
paulk-asert opened a new pull request, #3010:
URL: https://github.com/apache/groovy/pull/3010
…d to access a static field or call a static method
Under static compilation a static member reached through an expression
compiled to a bare GETSTATIC or INVOKESTATIC, so the expression itself never
ran and its side effects were lost. Java evaluates it and discards the value
(JLS 15.11.1, 15.12.4.1), as do dynamic Groovy and @TypeChecked.
There were three places that skipped it:
InvocationWriter.writeDirectMethodCall visited the receiver only for an
instance target (this also covers static properties, which are read and written
through their accessors); StaticTypesCallSiteWriter.makeGetField emitted
GETSTATIC directly; and the static-extension path in StaticInvocationWriter
passed null in its place. Each now evaluates and pops the receiver first,
unless it is a class literal, a variable or the implicit this, which cannot
have side effects, so the common forms compile as before.
StaticInvocationWriter no longer wraps the receiver of a static target in a
checkcast, which would fail for a Class-typed receiver.
> SC: receiver expression is not evaluated when it is used to access a static
> field or call a static method
> ---------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12479
> URL: https://issues.apache.org/jira/browse/GROOVY-12479
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 4.0.33, 5.1.3, 6.0.0
> Reporter: Paul King
> Assignee: Paul King
> Priority: Major
>
> Under {{@CompileStatic}}, when a static field or static method is reached
> through a receiver expression rather than a class name, the receiver
> expression is never evaluated. Any side effects it has are silently lost.
> Dynamic Groovy and {{@TypeChecked}} evaluate it, as Java does (JLS 15.11.1,
> 15.12.4.1: for a static member the receiver expression is evaluated and the
> result discarded).
> {code:groovy}
> class K { static final String CONST = 'c'; static String stat() { 's' } }
> class Probe {
> static List log = []
> static Class<Integer> pickClass() { log << 'pickClass'; Integer }
> static K pickInstance() { log << 'pickInstance'; new K() }
> }
> @groovy.transform.CompileStatic
> class CS {
> static a() { Probe.pickClass().MAX_VALUE } // static field via
> Class-typed expression
> static b() { Probe.pickInstance().CONST } // static field via
> instance-typed expression
> static c() { Probe.pickInstance().stat() } // static method via
> instance-typed expression
> static d() { Probe.pickClass().valueOf(1) } // static method via
> Class-typed expression
> }
> Probe.log.clear(); CS.a(); assert Probe.log == ['pickClass'] // fails: []
> Probe.log.clear(); CS.b(); assert Probe.log == ['pickInstance'] // fails: []
> Probe.log.clear(); CS.c(); assert Probe.log == ['pickInstance'] // fails: []
> Probe.log.clear(); CS.d(); assert Probe.log == ['pickClass'] // fails: []
> {code}
> The values are correct in every case; only the evaluation of the receiver is
> missing.
> ||Case||@CompileStatic||@TypeChecked||dynamic||
> |{{pickClass().MAX_VALUE}}|not evaluated|evaluated|evaluated|
> |{{pickInstance().CONST}}|not evaluated|evaluated|evaluated|
> |{{pickInstance().stat()}}|not evaluated|-|-|
> |{{pickClass().valueOf(1)}}|not evaluated|-|-|
> Same behaviour in 4.0.32, 5.1.2, 6.0.0 and master.
> *Expected:* the receiver expression is evaluated once, its value discarded,
> and the static member accessed, so the static-compiled result matches dynamic
> Groovy and Java.
> *Workaround:* evaluate the expression separately (e.g. {{def c = pickClass();
> c.MAX_VALUE}}), or access the member through the class name.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)