diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 46acaf7789..7facf3ade3 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -309,12 +309,12 @@ public class ResolvableType implements Serializable { // Deal with wildcard bounds WildcardBounds ourBounds = WildcardBounds.get(this); - WildcardBounds typeBounds = WildcardBounds.get(other); + WildcardBounds otherBounds = WildcardBounds.get(other); // In the form X is assignable to - if (typeBounds != null) { - return (ourBounds != null && ourBounds.isSameKind(typeBounds) && - ourBounds.isAssignableFrom(typeBounds.getBounds())); + if (otherBounds != null) { + return (ourBounds != null && ourBounds.isSameKind(otherBounds) && + ourBounds.isAssignableFrom(otherBounds.getBounds())); } // In the form is assignable to X... @@ -365,8 +365,8 @@ public class ResolvableType implements Serializable { if (checkGenerics) { // Recursively check each generic ResolvableType[] ourGenerics = getGenerics(); - ResolvableType[] typeGenerics = other.as(ourResolved).getGenerics(); - if (ourGenerics.length != typeGenerics.length) { + ResolvableType[] otherGenerics = other.as(ourResolved).getGenerics(); + if (ourGenerics.length != otherGenerics.length) { return false; } if (ourGenerics.length > 0) { @@ -375,7 +375,7 @@ public class ResolvableType implements Serializable { } matchedBefore.put(this.type, other.type); for (int i = 0; i < ourGenerics.length; i++) { - if (!ourGenerics[i].isAssignableFrom(typeGenerics[i], true, matchedBefore)) { + if (!ourGenerics[i].isAssignableFrom(otherGenerics[i], true, matchedBefore)) { return false; } } diff --git a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java index 7880ca35d3..0d4a389b45 100644 --- a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java +++ b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -169,7 +169,7 @@ class ResolvableTypeTests { @Test void forInstanceProviderNull() { - ResolvableType type = ResolvableType.forInstance(new MyGenericInterfaceType(null)); + ResolvableType type = ResolvableType.forInstance(new MyGenericInterfaceType<>(null)); assertThat(type.getType()).isEqualTo(MyGenericInterfaceType.class); assertThat(type.resolve()).isEqualTo(MyGenericInterfaceType.class); } @@ -1177,6 +1177,20 @@ class ResolvableTypeTests { assertThatResolvableType(complex4).isNotAssignableFrom(complex3); } + @Test + void isAssignableFromForUnresolvedWildcards() { + ResolvableType wildcard = ResolvableType.forInstance(new Wildcard<>()); + ResolvableType wildcardFixed = ResolvableType.forInstance(new WildcardFixed()); + ResolvableType wildcardConcrete = ResolvableType.forClassWithGenerics(Wildcard.class, Number.class); + + assertThat(wildcard.isAssignableFrom(wildcardFixed)).isTrue(); + assertThat(wildcard.isAssignableFrom(wildcardConcrete)).isTrue(); + assertThat(wildcardFixed.isAssignableFrom(wildcard)).isFalse(); + assertThat(wildcardFixed.isAssignableFrom(wildcardConcrete)).isFalse(); + assertThat(wildcardConcrete.isAssignableFrom(wildcard)).isTrue(); + assertThat(wildcardConcrete.isAssignableFrom(wildcardFixed)).isFalse(); + } + @Test void identifyTypeVariable() throws Exception { Method method = ClassArguments.class.getMethod("typedArgumentFirst", Class.class, Class.class, Class.class); @@ -1574,7 +1588,6 @@ class ResolvableTypeTests { } } - public class MySimpleInterfaceType implements MyInterfaceType { } @@ -1584,7 +1597,6 @@ class ResolvableTypeTests { public abstract class ExtendsMySimpleInterfaceTypeWithImplementsRaw extends MySimpleInterfaceTypeWithImplementsRaw { } - public class MyCollectionInterfaceType implements MyInterfaceType> { } @@ -1592,20 +1604,17 @@ class ResolvableTypeTests { public abstract class MySuperclassType { } - public class MySimpleSuperclassType extends MySuperclassType { } - public class MyCollectionSuperclassType extends MySuperclassType> { } - interface Wildcard extends List { + public class Wildcard { } - - interface RawExtendsWildcard extends Wildcard { + public class WildcardFixed extends Wildcard { }