Copilot commented on code in PR #2828:
URL: https://github.com/apache/groovy/pull/2828#discussion_r3837894972
##########
src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java:
##########
@@ -2522,10 +2534,32 @@ private boolean isStaticInContext(final MethodNode
method) {
return method instanceof ExtensionMethodNode ? ((ExtensionMethodNode)
method).isStaticExtension() : method.isStatic();
}
- private boolean storeField(final FieldNode field, final PropertyExpression
expressionToStoreOn, final ClassNode receiver, final ClassCodeVisitorSupport
visitor, final String delegationData, final boolean lhsOfAssignment) {
- boolean superField =
isSuperExpression(expressionToStoreOn.getObjectExpression());
- boolean accessible = (!superField &&
receiver.equals(field.getDeclaringClass()) &&
!field.getDeclaringClass().isAbstract()) // GROOVY-7300, GROOVY-11358
+ /**
+ * Determines if the field can back the given property (or attribute)
+ * expression: accessible by Java rules, or admitted by the receiver-type
+ * leniency (GROOVY-7300, GROOVY-11358) that models dynamic Groovy's
+ * permissive private access. Since GROOVY-12290 that leniency no longer
+ * admits plain property syntax to a private field of a foreign nest — a
+ * direct field access that static compilation cannot honour (no access
+ * bridge exists). The deliberate dynamic escape hatches remain: attribute
+ * access (.@), and closure bodies (GROOVY-9195) — including
delegate-resolved
+ * access — whose property dispatch stays dynamic-capable under static
compilation.
+ */
+ private boolean isFieldAccessible(final FieldNode field, final ClassNode
receiver, final PropertyExpression expression, final String delegationData) {
+ boolean superField =
isSuperExpression(expression.getObjectExpression());
+ boolean exactReceiver = (!superField &&
receiver.equals(field.getDeclaringClass()) &&
!field.getDeclaringClass().isAbstract()); // GROOVY-7300, GROOVY-11358
+ if (exactReceiver && field.isPrivate() && delegationData == null
+ && typeCheckingContext.getEnclosingClosure() == null
+ && !(expression instanceof AttributeExpression)
+ && getNestHost(field.getDeclaringClass()) !=
getNestHost(typeCheckingContext.getEnclosingClassNode())) {
Review Comment:
The foreign-nest check uses reference inequality (`!=`) on the `ClassNode`
returned by `getNestHost(...)`. Elsewhere in this class nest-host comparisons
use `.equals(...)`, and `ClassNode` instances representing the same type are
not guaranteed to be the same object. Using `!=` can incorrectly treat
same-nest accesses as “foreign nest”, changing accessibility/readonly behavior.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]