Skip to content

Commit ad849fb

Browse files
committed
Accept assignable match for covariant return type
See gh-35936 (cherry picked from commit df27627)
1 parent 8041a09 commit ad849fb

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,15 @@ private static boolean isResolvedTypeMatch(Method genericMethod, Method candidat
202202
private static boolean checkResolvedTypeMatch(Method genericMethod, Method candidateMethod, Class<?> clazz) {
203203
// First, compare return type.
204204
ResolvableType genericReturnType = ResolvableType.forMethodReturnType(genericMethod, clazz);
205-
if (!ClassUtils.resolvePrimitiveIfNecessary(candidateMethod.getReturnType()).equals(
206-
ClassUtils.resolvePrimitiveIfNecessary(genericReturnType.toClass()))) {
205+
if (!ClassUtils.resolvePrimitiveIfNecessary(genericReturnType.toClass()).isAssignableFrom(
206+
ClassUtils.resolvePrimitiveIfNecessary(candidateMethod.getReturnType()))) {
207207
return false;
208208
}
209209
Class<?>[] candidateParameters = candidateMethod.getParameterTypes();
210210
for (int i = 0; i < candidateParameters.length; i++) {
211211
ResolvableType genericParameter = ResolvableType.forMethodParameter(genericMethod, i, clazz);
212-
if (!ClassUtils.resolvePrimitiveIfNecessary(candidateParameters[i]).equals(
213-
ClassUtils.resolvePrimitiveIfNecessary(genericParameter.toClass()))) {
212+
if (!ClassUtils.resolvePrimitiveIfNecessary(genericParameter.toClass()).equals(
213+
ClassUtils.resolvePrimitiveIfNecessary(candidateParameters[i]))) {
214214
return false;
215215
}
216216
}

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

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ else if (method.getName().equals("getValues")) {
113113
}
114114
}
115115

116+
@Test
117+
void findBridgedMethodForCovariantReturnType() throws Exception {
118+
Method originalMethod = OuterSubclass.class.getDeclaredMethod("getInner");
119+
for (Method method: OuterSubclass.class.getDeclaredMethods()) {
120+
assertThat(BridgeMethodResolver.findBridgedMethod(method)).isEqualTo(originalMethod);
121+
}
122+
}
123+
116124
@Test
117125
void findBridgedMethodInHierarchyWithBoundedGenerics() throws Exception {
118126
Method originalMethod = Bar.class.getDeclaredMethod("someMethod", Object.class, Object.class);
@@ -425,6 +433,7 @@ void someMethod(T theArg, Object otherArg) {
425433
public abstract static class SubBar<T extends StringProducer> extends InterBar<T> {
426434
}
427435

436+
428437
public interface StringProducer extends CharSequence {
429438
}
430439

@@ -506,6 +515,31 @@ static class ConcreteMethods implements DefaultMethods {
506515
}
507516

508517

518+
static class Outer {
519+
520+
Inner getInner() {
521+
return new Inner();
522+
}
523+
}
524+
525+
526+
static class OuterSubclass extends Outer {
527+
528+
@Override
529+
InnerSubclass getInner() {
530+
return new InnerSubclass();
531+
}
532+
}
533+
534+
535+
static class Inner {
536+
}
537+
538+
539+
static class InnerSubclass extends Inner {
540+
}
541+
542+
509543
public static class Enclosing<T> {
510544

511545
public class Enclosed<S> {
@@ -899,22 +933,18 @@ public interface Receiver<E extends Event> {
899933

900934

901935
public interface MessageBroadcaster extends Receiver<MessageEvent> {
902-
903936
}
904937

905938

906939
public static class RemovedMessageEvent extends MessageEvent {
907-
908940
}
909941

910942

911943
public static class NewMessageEvent extends MessageEvent {
912-
913944
}
914945

915946

916947
public static class ModifiedMessageEvent extends MessageEvent {
917-
918948
}
919949

920950

0 commit comments

Comments
 (0)