[
https://issues.apache.org/jira/browse/GROOVY-11770?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18076851#comment-18076851
]
ASF GitHub Bot commented on GROOVY-11770:
-----------------------------------------
Copilot commented on code in PR #2498:
URL: https://github.com/apache/groovy/pull/2498#discussion_r3154481414
##########
src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java:
##########
@@ -273,11 +278,15 @@ private static ClassNode
parameterizeLowestUpperBound(final ClassNode lub, final
if (areEqualWithGenerics(t1, isPrimitiveType(a)?getWrapper(a):a)
&& areEqualWithGenerics(t2, isPrimitiveType(b)?getWrapper(b):b)) {
// "String implements Comparable<String>" and "StringBuffer
implements Comparable<StringBuffer>"
basicType = fallback; // do not loop
+ } else if (ctx.isExpanding(t1, t2)) {
+ // GROOVY-11770: structural cycle (e.g. LUB(B, D) where B
extends A<W<B>>, D extends A<W<D>>)
Review Comment:
The comment says “structural cycle”, but the guard currently detects cycles
using identity (`TypePair` uses `==`). Either adjust the wording to reflect
identity-based detection, or change the keying strategy to something
structural/stable so the comment matches the behavior.
```suggestion
// GROOVY-11770: recursion guard for an already-expanding
type pair (e.g. LUB(B, D) where B extends A<W<B>>, D extends A<W<D>>)
```
##########
src/test/groovy/groovy/transform/stc/GenericsSTCTest.groovy:
##########
@@ -4616,6 +4616,26 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase
{
}
}
+ // GROOVY-11770
+ @Test
+ void testNoStackOverflow3() {
+ // Cycle through a wrapper type: LUB(B, D) needs LUB(W<B>, W<D>),
+ // which needs LUB(B, D) again. Caught by structural cycle guard.
Review Comment:
This test comment says the cycle is “caught by structural cycle guard”, but
the new guard in `WideningCategories` is identity-based (and may not be
structural if new `ClassNode` instances are created). Suggest rewording the
comment to match the implementation (e.g., “caught by in-flight LUB pair
guard”).
```suggestion
// which needs LUB(B, D) again. Caught by the in-flight LUB pair
guard.
```
##########
src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java:
##########
@@ -273,11 +278,15 @@ private static ClassNode
parameterizeLowestUpperBound(final ClassNode lub, final
if (areEqualWithGenerics(t1, isPrimitiveType(a)?getWrapper(a):a)
&& areEqualWithGenerics(t2, isPrimitiveType(b)?getWrapper(b):b)) {
// "String implements Comparable<String>" and "StringBuffer
implements Comparable<StringBuffer>"
basicType = fallback; // do not loop
+ } else if (ctx.isExpanding(t1, t2)) {
+ // GROOVY-11770: structural cycle (e.g. LUB(B, D) where B
extends A<W<B>>, D extends A<W<D>>)
+ basicType = fallback;
} else {
+ ctx.enter(t1, t2);
try {
- basicType = lowestUpperBound(t1, t2);
- } catch (StackOverflowError ignore) {
- basicType = fallback; // best we can do for now
+ basicType = lowestUpperBound(ctx, t1, t2);
Review Comment:
`LowestUpperBoundContext` uses identity to track in-flight `(t1, t2)` pairs.
However, generics rewriting utilities (e.g.,
`correctToGenericsSpecRecurse`/`makeClassSafe0`) can produce fresh `ClassNode`
instances for the same logical type, which can defeat identity-based cycle
detection; with the `StackOverflowError` catch removed, a missed cycle could
reintroduce a hard SOE. Consider keeping the SOE catch as a last-resort
backstop, or normalizing the tracked pair to a stable representation (redirect
+ generics signature) so logically-equal nodes match.
```suggestion
basicType = lowestUpperBound(ctx, t1, t2);
} catch (StackOverflowError ignore) {
// Some generics-rewriting paths can create fresh
ClassNode instances for the same
// logical type, which may defeat identity-based cycle
tracking in the context.
// Fall back rather than allowing an unbounded recursive
expansion to overflow.
basicType = fallback;
```
> StackOverflowError processing generics for kubernetes-client library
> --------------------------------------------------------------------
>
> Key: GROOVY-11770
> URL: https://issues.apache.org/jira/browse/GROOVY-11770
> Project: Groovy
> Issue Type: Bug
> Reporter: Paul King
> Assignee: Paul King
> Priority: Major
> Fix For: 4.0.29, 5.0.2
>
>
> When processing a file using the kubernetes-client library, the Groovy
> compiler recurses endlessly parsing the generics.
> Repo:
> https://github.com/paulk-asert/kubernetes_client_stackoverflow
> This is just a reproducer which excludes Grails from this Grails issue/repo:
> https://github.com/apache/grails-core/issues/15082
> https://github.com/jdaugherty/grails-issue-stackoverflow-on-compile
--
This message was sent by Atlassian Jira
(v8.20.10#820010)