Skip to content

Commit

Permalink
Fix ResolvableType isAssignableFrom for <?>
Browse files Browse the repository at this point in the history
Fix ResolvableType.isAssignableFrom to correctly deal with <?> style
generics.

Issue: SPR-10973
  • Loading branch information
Phillip Webb committed Oct 10, 2013
1 parent 501a1cb commit 5358cc0
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private boolean isAssignableFrom(ResolvableType type, boolean checkingGeneric) {
Assert.notNull(type, "Type must not be null");

// If we cannot resolve types, we are not assignable
if (resolve() == null || type.resolve() == null) {
if (this == NONE || type == NONE) {
return false;
}

Expand All @@ -164,15 +164,16 @@ private boolean isAssignableFrom(ResolvableType type, boolean checkingGeneric) {
}

// Main assignability check
boolean rtn = resolve().isAssignableFrom(type.resolve());
boolean rtn = resolve(Object.class).isAssignableFrom(type.resolve(Object.class));

// We need an exact type match for generics
// List<CharSequence> is not assignable from List<String>
rtn &= (!checkingGeneric || resolve().equals(type.resolve()));
rtn &= (!checkingGeneric || resolve(Object.class).equals(type.resolve(Object.class)));

// Recursively check each generic
for (int i = 0; i < getGenerics().length; i++) {
rtn &= getGeneric(i).isAssignableFrom(type.as(resolve()).getGeneric(i), true);
rtn &= getGeneric(i).isAssignableFrom(
type.as(resolve(Object.class)).getGeneric(i), true);
}

return rtn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;

// FIXME nested

/**
* Tests for {@link ResolvableType}.
*
Expand Down Expand Up @@ -822,8 +820,8 @@ public void isAssignableFromCannotBeResolved() throws Exception {
ResolvableType objectType = ResolvableType.forClass(Object.class);
ResolvableType unresolvableVariable = ResolvableType.forField(AssignmentBase.class.getField("o"));
assertThat(unresolvableVariable.resolve(), nullValue());
assertAssignable(objectType, unresolvableVariable).equalTo(false);
assertAssignable(unresolvableVariable, objectType).equalTo(false);
assertAssignable(objectType, unresolvableVariable).equalTo(true);
assertAssignable(unresolvableVariable, objectType).equalTo(true);
}

@Test
Expand Down Expand Up @@ -936,6 +934,7 @@ public void isAssignableFromForWildcards() throws Exception {
ResolvableType object = ResolvableType.forClass(Object.class);
ResolvableType charSequence = ResolvableType.forClass(CharSequence.class);
ResolvableType string = ResolvableType.forClass(String.class);
ResolvableType extendsAnon = ResolvableType.forField(AssignmentBase.class.getField("listAnon"), Assignment.class).getGeneric();
ResolvableType extendsObject = ResolvableType.forField(AssignmentBase.class.getField("listxo"), Assignment.class).getGeneric();
ResolvableType extendsCharSequence = ResolvableType.forField(AssignmentBase.class.getField("listxc"), Assignment.class).getGeneric();
ResolvableType extendsString = ResolvableType.forField(AssignmentBase.class.getField("listxs"), Assignment.class).getGeneric();
Expand Down Expand Up @@ -972,6 +971,8 @@ public void isAssignableFromForWildcards() throws Exception {
equalTo(false, true, true);
assertAssignable(charSequence, extendsObject, extendsCharSequence, extendsString).
equalTo(false, false, false);
assertAssignable(extendsAnon, object, charSequence, string).
equalTo(true, true, true);

// T <= ? super T
assertAssignable(superCharSequence, object, charSequence, string).
Expand Down Expand Up @@ -1144,6 +1145,8 @@ static class AssignmentBase<O, C, S> {

public List<S> lists;

public List<?> listAnon;

public List<? extends O> listxo;

public List<? extends C> listxc;
Expand Down

0 comments on commit 5358cc0

Please sign in to comment.