Skip to content

Commit b5dd0a6

Browse files
committed
Restore lenient match against unresolvable wildcard
Closes gh-33982
1 parent e618f92 commit b5dd0a6

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

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

+10-9
Original file line numberDiff line numberDiff line change
@@ -334,19 +334,19 @@ private boolean isAssignableFrom(ResolvableType other, boolean strict,
334334

335335
// Deal with wildcard bounds
336336
WildcardBounds ourBounds = WildcardBounds.get(this);
337-
WildcardBounds typeBounds = WildcardBounds.get(other);
337+
WildcardBounds otherBounds = WildcardBounds.get(other);
338338

339339
// In the form X is assignable to <? extends Number>
340-
if (typeBounds != null) {
340+
if (otherBounds != null) {
341341
if (ourBounds != null) {
342-
return (ourBounds.isSameKind(typeBounds) &&
343-
ourBounds.isAssignableFrom(typeBounds.getBounds(), matchedBefore));
342+
return (ourBounds.isSameKind(otherBounds) &&
343+
ourBounds.isAssignableFrom(otherBounds.getBounds(), matchedBefore));
344344
}
345345
else if (upUntilUnresolvable) {
346-
return typeBounds.isAssignableFrom(this, matchedBefore);
346+
return otherBounds.isAssignableFrom(this, matchedBefore);
347347
}
348348
else if (!exactMatch) {
349-
return typeBounds.isAssignableTo(this, matchedBefore);
349+
return otherBounds.isAssignableTo(this, matchedBefore);
350350
}
351351
else {
352352
return false;
@@ -400,8 +400,8 @@ else if (!exactMatch) {
400400
if (checkGenerics) {
401401
// Recursively check each generic
402402
ResolvableType[] ourGenerics = getGenerics();
403-
ResolvableType[] typeGenerics = other.as(ourResolved).getGenerics();
404-
if (ourGenerics.length != typeGenerics.length) {
403+
ResolvableType[] otherGenerics = other.as(ourResolved).getGenerics();
404+
if (ourGenerics.length != otherGenerics.length) {
405405
return false;
406406
}
407407
if (ourGenerics.length > 0) {
@@ -410,7 +410,8 @@ else if (!exactMatch) {
410410
}
411411
matchedBefore.put(this.type, other.type);
412412
for (int i = 0; i < ourGenerics.length; i++) {
413-
if (!ourGenerics[i].isAssignableFrom(typeGenerics[i], true, matchedBefore, upUntilUnresolvable)) {
413+
if (!ourGenerics[i].isAssignableFrom(otherGenerics[i],
414+
!other.hasUnresolvableGenerics(), matchedBefore, upUntilUnresolvable)) {
414415
return false;
415416
}
416417
}

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

+22-7
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,26 @@ void isAssignableFromForComplexWildcards() throws Exception {
11881188
assertThatResolvableType(complex4).isNotAssignableFrom(complex3);
11891189
}
11901190

1191+
@Test
1192+
void isAssignableFromForUnresolvedWildcards() {
1193+
ResolvableType wildcard = ResolvableType.forInstance(new Wildcard<>());
1194+
ResolvableType wildcardFixed = ResolvableType.forInstance(new WildcardFixed());
1195+
ResolvableType wildcardConcrete = ResolvableType.forClassWithGenerics(Wildcard.class, Number.class);
1196+
1197+
assertThat(wildcard.isAssignableFrom(wildcardFixed)).isTrue();
1198+
assertThat(wildcard.isAssignableFromResolvedPart(wildcardFixed)).isTrue();
1199+
assertThat(wildcard.isAssignableFrom(wildcardConcrete)).isTrue();
1200+
assertThat(wildcard.isAssignableFromResolvedPart(wildcardConcrete)).isTrue();
1201+
assertThat(wildcardFixed.isAssignableFrom(wildcard)).isFalse();
1202+
assertThat(wildcardFixed.isAssignableFromResolvedPart(wildcard)).isFalse();
1203+
assertThat(wildcardFixed.isAssignableFrom(wildcardConcrete)).isFalse();
1204+
assertThat(wildcardFixed.isAssignableFromResolvedPart(wildcardConcrete)).isFalse();
1205+
assertThat(wildcardConcrete.isAssignableFrom(wildcard)).isTrue();
1206+
assertThat(wildcardConcrete.isAssignableFromResolvedPart(wildcard)).isTrue();
1207+
assertThat(wildcardConcrete.isAssignableFrom(wildcardFixed)).isFalse();
1208+
assertThat(wildcardConcrete.isAssignableFromResolvedPart(wildcardFixed)).isFalse();
1209+
}
1210+
11911211
@Test
11921212
void identifyTypeVariable() throws Exception {
11931213
Method method = ClassArguments.class.getMethod("typedArgumentFirst", Class.class, Class.class, Class.class);
@@ -1685,7 +1705,6 @@ public ResolvableType getResolvableType() {
16851705
}
16861706
}
16871707

1688-
16891708
public class MySimpleInterfaceType implements MyInterfaceType<String> {
16901709
}
16911710

@@ -1695,28 +1714,24 @@ public abstract class MySimpleInterfaceTypeWithImplementsRaw implements MyInterf
16951714
public abstract class ExtendsMySimpleInterfaceTypeWithImplementsRaw extends MySimpleInterfaceTypeWithImplementsRaw {
16961715
}
16971716

1698-
16991717
public class MyCollectionInterfaceType implements MyInterfaceType<Collection<String>> {
17001718
}
17011719

17021720

17031721
public abstract class MySuperclassType<T> {
17041722
}
17051723

1706-
17071724
public class MySimpleSuperclassType extends MySuperclassType<String> {
17081725
}
17091726

1710-
17111727
public class MyCollectionSuperclassType extends MySuperclassType<Collection<String>> {
17121728
}
17131729

17141730

1715-
interface Wildcard<T extends Number> extends List<T> {
1731+
public class Wildcard<T extends Number> {
17161732
}
17171733

1718-
1719-
interface RawExtendsWildcard extends Wildcard {
1734+
public class WildcardFixed extends Wildcard<Integer> {
17201735
}
17211736

17221737

0 commit comments

Comments
 (0)