Skip to content

Commit 2df05fe

Browse files
committed
Consider nested generics in TypeDiscoverer equality comparison.
We now compare nested generics wrapped into TypeInformation to consider type equality for deeply parametrized types. Previously, we resolved type parameters to Class so Foo<List<String>> was considered equal to Foo<List<Map>> as the type parameter of the first nesting level was erased. Closes #3051
1 parent c0ae3ab commit 2df05fe

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/main/java/org/springframework/data/util/TypeDiscoverer.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
6060
private final Map<Constructor<?>, List<TypeInformation<?>>> constructorParameters = new ConcurrentHashMap<>();
6161
private final Lazy<List<TypeInformation<?>>> typeArguments;
6262

63-
private final Lazy<List<Class>> resolvedGenerics;
63+
private final Lazy<List<TypeInformation<?>>> resolvedGenerics;
6464

6565
protected TypeDiscoverer(ResolvableType type) {
6666

@@ -71,7 +71,9 @@ protected TypeDiscoverer(ResolvableType type) {
7171
this.valueType = Lazy.of(this::doGetMapValueType);
7272
this.typeArguments = Lazy.of(this::doGetTypeArguments);
7373
this.resolvedGenerics = Lazy.of(() -> Arrays.stream(resolvableType.getGenerics()) //
74-
.map(ResolvableType::toClass).collect(Collectors.toList()));
74+
.map(TypeInformation::of) // use TypeInformation comparison to remove any attachments to variableResolver
75+
// holding the type source
76+
.collect(Collectors.toList()));
7577
}
7678

7779
static TypeDiscoverer<?> td(ResolvableType type) {

src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java

+21
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.junit.jupiter.api.Test;
3030
import org.junit.jupiter.api.extension.ExtendWith;
3131
import org.mockito.junit.jupiter.MockitoExtension;
32+
3233
import org.springframework.beans.factory.annotation.Autowire;
3334
import org.springframework.core.ResolvableType;
3435
import org.springframework.data.geo.GeoResults;
@@ -348,6 +349,15 @@ void differentEqualsAndHashCodeForTypeDiscovererAndClassTypeInformation() {
348349
assertThat(discoverer.hashCode()).isNotEqualTo(classTypeInformation.hashCode());
349350
}
350351

352+
@Test // GH-3051
353+
void considersNestedGenericsInEquality() throws ReflectiveOperationException {
354+
355+
ResolvableType containerList = ResolvableType.forField(WithContainer.class.getDeclaredField("containerList"));
356+
ResolvableType containerMap = ResolvableType.forField(WithContainer.class.getDeclaredField("containerMap"));
357+
358+
assertThat(TypeInformation.of(containerList)).isNotEqualTo(TypeInformation.of(containerMap));
359+
}
360+
351361
class Person {
352362

353363
Addresses addresses;
@@ -441,4 +451,15 @@ class EnumMapWrapper {
441451
class GeoResultsWrapper {
442452
GeoResults<Leaf> results;
443453
}
454+
455+
static class WithContainer {
456+
MyContainer<List<String>> containerList;
457+
458+
MyContainer<List<Map<Long, Double>>> containerMap;
459+
}
460+
461+
static class MyContainer<T> {
462+
T data;
463+
}
464+
444465
}

0 commit comments

Comments
 (0)