Skip to content

Commit 687bd28

Browse files
committed
Be more permissive with CastingConverter casts
1 parent ce135b7 commit 687bd28

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/main/java/org/scijava/convert/CastingConverter.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,30 @@ public boolean canConvert(final Object src, final Class<?> dest) {
4949

5050
@Override
5151
public boolean canConvert(final Class<?> src, final Type dest) {
52-
// OK if the existing object can be casted
53-
return dest != null && Types.isAssignable(src, dest);
52+
// NB: You might think we want to use Types.isAssignable(src, dest)
53+
// directly here. And you might be right. However, assignment involving
54+
// generic types gets very tricky. If dest is e.g. a wildcard type such as
55+
// "? extends Object", or a type variable such as "C extends Object", then
56+
// no specific class will be assignable to it, because for that ? or C we
57+
// do not know anything about the bound type other than that it's something
58+
// that extends Object, so it could be anything, including things that
59+
// aren't assignable from whatever src is.
60+
//
61+
// Unfortunately, when this casting conversion code was originally written,
62+
// it did not have generics in mind, and calling code will pass in capture
63+
// types (e.g. Type objects gleaned via ModuleItem#getGenericType())
64+
// expecting them to be convertible as long as dest's raw type(s) are
65+
// compatible targets for src.
66+
//
67+
// And so for backwards compatibility, we continue to behave that way here.
68+
69+
return dest != null && //
70+
Types.raws(dest).stream().allMatch(c -> c.isAssignableFrom(src));
5471
}
5572

5673
@Override
5774
public boolean canConvert(final Class<?> src, final Class<?> dest) {
58-
// NB: Invert functional flow from Converter interface:
59-
// Converter: canConvert(Class, Type) -> canConvert(Class, Class)
60-
// becomes: canConvert(Class, Class) -> canConvert(Class, Type)
61-
final Type destType = dest;
62-
return canConvert(src, destType);
75+
return dest != null && dest.isAssignableFrom(src);
6376
}
6477

6578
@Override

0 commit comments

Comments
 (0)