Copilot commented on code in PR #2635:
URL: https://github.com/apache/groovy/pull/2635#discussion_r3486973642
##########
src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java:
##########
@@ -82,17 +82,21 @@ public List<MethodNode> handleMissingMethod(final ClassNode
receiver, final Stri
ClassNode returnType =
mce.getNodeMetaData(TraitASTTransformation.DO_DYNAMIC);
if (returnType != null) return
Collections.singletonList(makeDynamic(call, returnType));
- // GROOVY-7322, GROOVY-8272, GROOVY-8587, GROOVY-8854,
GROOVY-10312: trait: this.m($static$self)
+ // GROOVY-7322, GROOVY-8272, GROOVY-8587, GROOVY-8854,
GROOVY-10312, GROOVY-12106: trait: this.m($static$self)
ClassNode targetClass =
isClassClassNodeWrappingConcreteType(receiver)?
receiver.getGenericsTypes()[0].getType(): receiver;
if (Traits.isTrait(targetClass.getOuterClass()) &&
argumentTypes.length > 0 && ClassHelper.isClassType(argumentTypes[0])) {
- Parameter[] signature =
java.util.Arrays.stream(argumentTypes).map(t -> new
Parameter(t,"")).toArray(Parameter[]::new);
List<ClassNode> traits =
Traits.findTraits(targetClass.getOuterClass());
traits.remove(targetClass.getOuterClass());
for (ClassNode trait : traits) { // check super trait for
static method
- MethodNode method =
Traits.findHelper(trait).getDeclaredMethod(name, signature);
- if (method != null && method.isStatic()) {
- return Collections.singletonList(makeDynamic(call,
method.getReturnType()));
+ // GROOVY-12106: resolve via the type checker rather than
an exact
+ // parameter-type match, so an argument whose static type
is a subtype
+ // of the declared parameter still resolves the inherited
helper static
+ // (matching how plain-class static inheritance behaves).
+ for (MethodNode method :
typeCheckingVisitor.findMethod(Traits.findHelper(trait), name, argumentTypes)) {
+ if (method.isStatic()) {
+ return Collections.singletonList(makeDynamic(call,
method.getReturnType()));
+ }
}
}
Review Comment:
`typeCheckingVisitor.findMethod` performs full STC method lookup (including
DGM/extension methods) and returns a best-match set with non-deterministic
iteration order when there are multiple best candidates. In this trait-helper
resolution path, that can (a) accidentally match an unrelated extension method
on the helper class and/or (b) pick an arbitrary overload’s return type when
multiple candidates tie, which can break downstream type-checking that relies
on `DYNAMIC_RESOLUTION`’s inferred return type. It would be safer and more
precise to restrict the search to the helper’s declared methods and then apply
subtype-aware overload selection (e.g.
`StaticTypeCheckingSupport.chooseBestMethod`) over just those static
candidates, falling back to `Object` if resolution is ambiguous.
--
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]