[LANG-1749] Add stricter type checks for parameterized types in method #1548
+38
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fix
TypeUtils.isAssignableforClassparameterized typesSummary
This PR fixes a bug in
TypeUtils.isAssignablewhere it incorrectly returnedtruefor certainParameterizedTypeassignments involvingjava.lang.Class. Specifically, it was allowing assignments likeClass<TestIF>toClass<? extends TestIF<?>>, which are prohibited by the Java compiler due to the invariance of theClass<T>type.Problem
In Java,
Class<T>is invariant. This means that even ifTestImplextendsTestIF,Class<TestImpl>is NOT assignable toClass<TestIF>. Furthermore,Class<TestIF>is not assignable toClass<? extends TestIF<?>>because the type argument of the latter is a wildcard that requires a specific capturing behavior that a raw-ish or differently parameterizedClassdoes not satisfy in the same way.The previous implementation of
TypeUtils.isAssignable(Type, ParameterizedType, Map)was too permissive when handlingClass.classas the raw type, treating it like any other parameterized interface or class instead of enforcing the strict invariance required forClass<T>.Solution
The fix introduces a specialized check within
isAssignable(Type, ParameterizedType, Map)when the target raw type isjava.lang.Class.ParameterizedTyperepresents aClass<?>.Classclass.Changes
org.apache.commons.lang3.reflect.TypeUtils:isAssignable(Type, ParameterizedType, Map)specifically forClass.class.Classtype arguments usingunrollVariableAssignmentsto resolve any type variables in the current context.Class<? extends Foo>), the source must match the captured type exactly or satisfy the bound without violating invariance.org.apache.commons.lang3.reflect.TypeUtilsTest:testIsAssignable_ClassWithParameterizedTypewhich includes:Class<TestIF>toClass<? extends TestIF<?>>(Expected:false)Class<TestImpl>toClass<? extends TestIF<?>>(Expected:false)Class<TestImpl2>toClass<? extends TestIF<Number>>(Expected:false)TestIF<T>,TestImpl<T>,TestImpl2<R>) to support these test cases.Note: Used AI tools in the writing of this PR - JetBrains AI. There are no copyright issues with the submitted code.