Alwaysgaurav1 opened a new pull request, #1789:
URL: https://github.com/apache/commons-lang/pull/1789

   ## Problem
   `TypeUtils.toString(Type)` suffered from several interrelated issues when 
handling recursive generic types and type bounds:
   1. **StackOverflowError on Recursive Generic Types**: Formatting recursive 
generic types like `class MySuperClass<T>`, `class MyClass<U extends 
MySuperClass<? super U>>`, or `class MultiBoundClass<U extends Number & 
Comparable<? super U>>` resulted in `StackOverflowError`.
   2. **Stripping of Valid Interface Bounds**: A workaround previously 
introduced for `LANG-1698` unconditionally skipped bounds if the raw type was 
an interface. This stripped all valid interface bounds (e.g. `<T extends 
List<String>>` formatted as `"T"` instead of `"T extends 
java.util.List<java.lang.String>"`), while still failing with a 
`StackOverflowError` on class bounds.
   3. **Corrupted Multi-Parameter Recursive Types**: Workaround methods 
`findRecursiveTypes` and `appendRecursiveTypes` corrupted type parameter 
formatting on multi-parameter recursive types (such as `TwoParams<T extends 
TwoParams<T, U>, U>`), outputting `<T><U><U>`.
   4. **Incomplete Multi-Bound Wildcard Inspection**: 
`TypeUtils.containsTypeVariables(WildcardType)` only inspected the bound at 
index `0`, ignoring subsequent bounds for multi-bounded wildcards.
   
   ## Root Cause
   In Java grammar (JLS Chapter 4), a `TypeVariable` is a **declaration** only 
when declaring a type parameter (e.g. `<U extends Number>`). Everywhere 
else—such as inside type arguments (`List<U>`), wildcard bounds (`? extends U`, 
`? super U`), generic arrays (`U[]`), or other type variable bounds (`<S 
extends T>`)—it is a **type reference** (`ReferenceType`) and should be 
formatted only by its identifier name `U`. Treating embedded type variables as 
declarations led to recursive expansion of bounds.
   
   ## Solution
   1. **Differentiate Type Declarations and References**: Added 
`toReferenceString(Type)` which formats `TypeVariable` instances by name only 
and delegates other types to `toString(Type)`. Configured `AMP_JOINER`, 
`TYPE_ARG_JOINER`, and `genericArrayTypeToString` to format embedded types as 
references.
   2. **Preserve Interface Bounds**: Removed the interface-check workaround 
from `typeVariableToString`, properly preserving all interface bounds without 
recursion.
   3. **Remove Workaround Heuristics**: Cleanly removed `findRecursiveTypes`, 
`appendRecursiveTypes`, and `containsVariableTypeSameParametrizedTypeBound`.
   4. **Inspect All Wildcard Bounds**: Updated 
`containsTypeVariables(WildcardType)` to check all implicit upper and lower 
bounds.
   5. **ThreadLocal Cycle Guard**: Added `VISITING` 
`ThreadLocal<Set<TypeVariable<?>>>` with guaranteed `VISITING.remove()` in 
`finally` to guard against arbitrary cyclical type graphs without leaking 
memory.
   
   ## Verification
   - All 430 tests in `TypeUtilsTest` passed (including 6 new tests covering 
recursive class bounds, multi-bounds, interface preservation, and multi-bound 
wildcards).
   - All 590 tests across `org.apache.commons.lang3.reflect.*` passed without 
regressions.


-- 
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]

Reply via email to