[ 
https://issues.apache.org/jira/browse/GROOVY-11022?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18077011#comment-18077011
 ] 

ASF GitHub Bot commented on GROOVY-11022:
-----------------------------------------

blackdrag commented on code in PR #2496:
URL: https://github.com/apache/groovy/pull/2496#discussion_r3159976554


##########
src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java:
##########
@@ -1789,9 +1794,22 @@ private static GenericsType applyGenericsContext(final 
Map<GenericsTypeName, Gen
             GenericsType specType = spec.get(name);
             if (specType != null) return specType;
             if (hasNonTrivialBounds(gt)) {
-                GenericsType newGT = new GenericsType(type, 
applyGenericsContext(spec, gt.getUpperBounds()), applyGenericsContext(spec, 
gt.getLowerBound()));
-                newGT.setPlaceholder(true);
-                return newGT;
+                // GROOVY-11022: avoid infinite recursion on F-bounded type
+                // parameters whose self-reference appears inside a wildcard
+                // bound (e.g. `<K extends Comparable<? super K>>`)
+                Deque<GenericsTypeName> expanding = EXPANDING_BOUNDS.get();
+                if (expanding.contains(name)) return gt;
+                expanding.push(name);
+                try {
+                    GenericsType newGT = new GenericsType(type, 
applyGenericsContext(spec, gt.getUpperBounds()), applyGenericsContext(spec, 
gt.getLowerBound()));
+                    newGT.setPlaceholder(true);
+                    return newGT;
+                } finally {
+                    expanding.pop();

Review Comment:
   so we push to expanding and then pop from expanding. That means we remove 
the entry we just added, even in the case of line 1806, with the return. Why is 
it then not always empty again? Ah, because of the recursive call 
applyGenericsContext(spec, gt.getLowerBound()). But why does it have to be a 
ThreadLocal then? I would prefere going for a breaking change here nstead of 
using ThreadLocal



##########
src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java:
##########
@@ -1769,6 +1771,9 @@ static GenericsType[] getGenericsWithoutArray(final 
ClassNode type) {
         return type.getGenericsTypes();
     }
 
+    private static final ThreadLocal<Deque<GenericsTypeName>> EXPANDING_BOUNDS 
=
+            ThreadLocal.withInitial(ArrayDeque::new);

Review Comment:
   I am very critical to using a ThreadLocal. At the very least there should be 
a description of why this has to be ThreadLocal 





> StackOverflowError when having parameterized function with recursive bounds
> ---------------------------------------------------------------------------
>
>                 Key: GROOVY-11022
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11022
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static Type Checker
>            Reporter: Thodoris Sotiropoulos
>            Assignee: Eric Milles
>            Priority: Critical
>              Labels: StackOverflowError, bounded-polymorphism
>
> I have the following program
> {code}
> class Test<K, V> {
>     public static <K extends Comparable<? super K>, V> Test<K, V> m(K k1, V 
> v1) {
>         return new Test<K, V>()
>     }
> }
> class Main {
>     @groovy.transform.TypeChecked test() {
>         Test.<Object, Integer>m(null, 1)
>     }
> }
> {code}
> h3. Actual behavior 
> {code}
>    >>> a serious error occurred: null
>    >>> stacktrace:
>    java.lang.StackOverflowError
>        at org.codehaus.groovy.ast.ClassNode.getText(ClassNode.java:1606)
>        at org.codehaus.groovy.ast.ClassNode.equals(ClassNode.java:729)
>        at 
> org.codehaus.groovy.ast.ClassHelper.isObjectType(ClassHelper.java:525)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.hasNonTrivialBounds(StaticTypeCheckingSupport.java:1880)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1833)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1843)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1890)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1834)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1843)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1890)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1834)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1843)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1890)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1834)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1843)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1890)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1834)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1821)
>        at 
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.applyGenericsContext(StaticTypeCheckingSupport.java:1905)
> ...
> {code}
> h3. Expected behavior
> Reject with type error
> Tested against master (commit: bbbff15b867157d8ed9f05207265a5ea80357ba6)



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to