Skip to content

Commit 3bb4795

Browse files
committed
Resolve variable bounds at outermost recursion level only
Closes gh-34504
1 parent aae2952 commit 3bb4795

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

Diff for: spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ public static Type resolveType(Type genericType, @Nullable Class<?> contextClass
159159
if (genericType instanceof TypeVariable<?> typeVariable) {
160160
ResolvableType resolvedTypeVariable = resolveVariable(
161161
typeVariable, ResolvableType.forClass(contextClass));
162+
if (resolvedTypeVariable == ResolvableType.NONE) {
163+
resolvedTypeVariable = ResolvableType.forVariableBounds(typeVariable);
164+
}
162165
if (resolvedTypeVariable != ResolvableType.NONE) {
163166
Class<?> resolved = resolvedTypeVariable.resolve();
164167
if (resolved != null) {
@@ -176,6 +179,9 @@ else if (genericType instanceof ParameterizedType parameterizedType) {
176179
Type typeArgument = typeArguments[i];
177180
if (typeArgument instanceof TypeVariable<?> typeVariable) {
178181
ResolvableType resolvedTypeArgument = resolveVariable(typeVariable, contextType);
182+
if (resolvedTypeArgument == ResolvableType.NONE) {
183+
resolvedTypeArgument = ResolvableType.forVariableBounds(typeVariable);
184+
}
179185
if (resolvedTypeArgument != ResolvableType.NONE) {
180186
generics[i] = resolvedTypeArgument;
181187
}
@@ -229,7 +235,7 @@ private static ResolvableType resolveVariable(TypeVariable<?> typeVariable, Reso
229235
return resolvedType;
230236
}
231237
}
232-
return ResolvableType.forVariableBounds(typeVariable);
238+
return ResolvableType.NONE;
233239
}
234240

235241
/**

Diff for: spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java

+23
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,13 @@ void resolveTypeWithUnresolvableElement() {
243243
assertThat(resolvedType.toString()).isEqualTo("java.util.List<E>");
244244
}
245245

246+
@Test
247+
void resolveTypeFromGenericDefaultMethod() {
248+
Type type = method(InterfaceWithDefaultMethod.class, "get", InheritsDefaultMethod.AbstractType.class).getGenericParameterTypes()[0];
249+
Type resolvedType = resolveType(type, InheritsDefaultMethod.class);
250+
assertThat(resolvedType).isEqualTo(InheritsDefaultMethod.ConcreteType.class);
251+
}
252+
246253
private static Method method(Class<?> target, String methodName, Class<?>... parameterTypes) {
247254
Method method = findMethod(target, methodName, parameterTypes);
248255
assertThat(method).describedAs(target.getName() + "#" + methodName).isNotNull();
@@ -454,4 +461,20 @@ List<T> get() {
454461
}
455462
}
456463

464+
public interface InterfaceWithDefaultMethod<T extends InheritsDefaultMethod.AbstractType> {
465+
466+
default String get(T input) {
467+
throw new UnsupportedOperationException();
468+
}
469+
470+
interface AbstractType {
471+
}
472+
}
473+
474+
public static class InheritsDefaultMethod implements InterfaceWithDefaultMethod<InheritsDefaultMethod.ConcreteType> {
475+
476+
static class ConcreteType implements AbstractType {
477+
}
478+
}
479+
457480
}

0 commit comments

Comments
 (0)