Skip to content

Commit ed994dc

Browse files
committed
Resolve bounds for type variable before emptiness check
Closes gh-34328
1 parent 4c3b435 commit ed994dc

File tree

3 files changed

+48
-22
lines changed

3 files changed

+48
-22
lines changed

spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ else if (genericType instanceof ParameterizedType parameterizedType) {
180180
generics[i] = resolvedTypeArgument;
181181
}
182182
else {
183-
generics[i] = ResolvableType.forType(typeArgument).resolveType();
183+
generics[i] = ResolvableType.forType(typeArgument);
184184
}
185185
}
186186
else if (typeArgument instanceof ParameterizedType) {
@@ -226,7 +226,7 @@ private static ResolvableType resolveVariable(TypeVariable<?> typeVariable, Reso
226226
return resolvedType;
227227
}
228228
}
229-
return ResolvableType.NONE;
229+
return ResolvableType.forVariableBounds(typeVariable);
230230
}
231231

232232
/**

spring-core/src/main/java/org/springframework/core/ResolvableType.java

+18-9
Original file line numberDiff line numberDiff line change
@@ -953,14 +953,6 @@ ResolvableType resolveType() {
953953
return NONE;
954954
}
955955

956-
@Nullable
957-
private Type resolveBounds(Type[] bounds) {
958-
if (bounds.length == 0 || bounds[0] == Object.class) {
959-
return null;
960-
}
961-
return bounds[0];
962-
}
963-
964956
@Nullable
965957
private ResolvableType resolveVariable(TypeVariable<?> variable) {
966958
if (this.type instanceof TypeVariable) {
@@ -1463,6 +1455,24 @@ public static ResolvableType forArrayComponent(ResolvableType componentType) {
14631455
return new ResolvableType(arrayType, componentType, null, null);
14641456
}
14651457

1458+
/**
1459+
* Return a {@code ResolvableType} for the bounds of the specified {@link TypeVariable}.
1460+
* @param typeVariable the type variable
1461+
* @return a {@code ResolvableType} for the specified bounds
1462+
* @since 6.2.3
1463+
*/
1464+
static ResolvableType forVariableBounds(TypeVariable<?> typeVariable) {
1465+
return forType(resolveBounds(typeVariable.getBounds()));
1466+
}
1467+
1468+
@Nullable
1469+
private static Type resolveBounds(Type[] bounds) {
1470+
if (bounds.length == 0 || bounds[0] == Object.class) {
1471+
return null;
1472+
}
1473+
return bounds[0];
1474+
}
1475+
14661476
/**
14671477
* Return a {@code ResolvableType} for the specified {@link Type}.
14681478
* <p>Note: The resulting {@code ResolvableType} instance may not be {@link Serializable}.
@@ -1491,7 +1501,6 @@ public static ResolvableType forType(@Nullable Type type, @Nullable ResolvableTy
14911501
return forType(type, variableResolver);
14921502
}
14931503

1494-
14951504
/**
14961505
* Return a {@code ResolvableType} for the specified {@link ParameterizedTypeReference}.
14971506
* <p>Note: The resulting {@code ResolvableType} instance may not be {@link Serializable}.

spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java

+28-11
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,27 @@ void resolveNestedTypeVariable() throws Exception {
212212
}
213213

214214
@Test
215-
void resolvedTypeWithBase() {
216-
Type type = method(WithBaseTypes.class, "get").getGenericReturnType();
217-
Type resolvedType = resolveType(type, WithBaseTypes.class);
215+
void resolveTypeWithElementBounds() {
216+
Type type = method(WithElementBounds.class, "get").getGenericReturnType();
217+
Type resolvedType = resolveType(type, WithElementBounds.class);
218218
ParameterizedTypeReference<List<A>> reference = new ParameterizedTypeReference<>() {};
219219
assertThat(resolvedType).isEqualTo(reference.getType());
220220
}
221221

222+
@Test
223+
void resolveTypeWithUnresolvableElement() {
224+
Type type = method(WithUnresolvableElement.class, "get").getGenericReturnType();
225+
Type resolvedType = resolveType(type, WithUnresolvableElement.class);
226+
assertThat(resolvedType.toString()).isEqualTo("java.util.List<E>");
227+
}
228+
222229
private static Method method(Class<?> target, String methodName, Class<?>... parameterTypes) {
223230
Method method = findMethod(target, methodName, parameterTypes);
224231
assertThat(method).describedAs(target.getName() + "#" + methodName).isNotNull();
225232
return method;
226233
}
227234

235+
228236
public interface MyInterfaceType<T> {
229237
}
230238

@@ -348,33 +356,35 @@ public static class MySimpleTypeWithMethods extends MyTypeWithMethods<Integer> {
348356
static class GenericClass<T> {
349357
}
350358

351-
class A{}
359+
class A {}
352360

353-
class B<T>{}
361+
class B<T> {}
354362

355363
class C extends A {}
356364

357365
class D extends B<Long> {}
358366

359367
class E extends C {}
360368

361-
class TestIfc<T>{}
369+
class TestIfc<T> {}
362370

363-
class TestImpl<I extends A, T extends B<I>> extends TestIfc<T>{
371+
class TestImpl<I extends A, T extends B<I>> extends TestIfc<T> {
364372
}
365373

366374
abstract static class BiGenericClass<T extends B<?>, V extends A> {}
367375

368-
abstract static class SpecializedBiGenericClass<U extends C> extends BiGenericClass<D, U>{}
376+
abstract static class SpecializedBiGenericClass<U extends C> extends BiGenericClass<D, U> {}
369377

370378
static class TypeFixedBiGenericClass extends SpecializedBiGenericClass<E> {}
371379

372380
static class TopLevelClass<T> {
381+
373382
class Nested<X> {
374383
}
375384
}
376385

377386
static class TypedTopLevelClass extends TopLevelClass<Integer> {
387+
378388
class TypedNested extends Nested<Long> {
379389
}
380390
}
@@ -394,24 +404,31 @@ interface IdFixingRepository<T> extends Repository<T, Long> {
394404
}
395405

396406
static class WithMethodParameter {
407+
397408
public void nestedGenerics(List<Map<String, Integer>> input) {
398409
}
399410
}
400411

401-
public interface ListOfListSupplier<T> {
412+
interface ListOfListSupplier<T> {
402413

403414
List<List<T>> get();
404415
}
405416

406-
public interface StringListOfListSupplier extends ListOfListSupplier<String> {
417+
interface StringListOfListSupplier extends ListOfListSupplier<String> {
407418
}
408419

409-
static class WithBaseTypes {
420+
static class WithElementBounds {
410421

411422
<T extends A> List<T> get() {
412423
return List.of();
413424
}
425+
}
426+
427+
static class WithUnresolvableElement<T> {
414428

429+
List<T> get() {
430+
return List.of();
431+
}
415432
}
416433

417434
}

0 commit comments

Comments
 (0)