[
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)