Fix supertypes consistency check
See testKt5508: `inner class B<S> : A<B<S>>()` is effectively the same as `A<T>.B<S> : A<A<T>.B<S>>` or `B<S, T> : A<B<S, T>>`. The latter is because we add outer class parameters to inner type constructor. The problem is that we treat type constructors of first TP of 'A' and of second type parameter (copy) of 'B' just the same and report INCONSISTENT_TYPE_PARAMETER_VALUES. So we supposse it's more correct to compare type parameter descriptors instead
This commit is contained in:
+2
-2
@@ -526,7 +526,7 @@ public class SignaturesPropagationData {
|
||||
// #1 of Baz -> A
|
||||
// #0 of Foo -> A (mapped to itself)
|
||||
// #1 of Foo -> B (mapped to itself)
|
||||
Multimap<TypeConstructor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
|
||||
Multimap<TypeParameterDescriptor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
|
||||
TypeUtils.makeUnsubstitutedType(klass, ErrorUtils.createErrorScope("Do not access this scope", true)));
|
||||
|
||||
// for each parameter of klass, hold arguments in corresponding supertypes
|
||||
@@ -547,7 +547,7 @@ public class SignaturesPropagationData {
|
||||
// 4. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#1 of Baz", argument = CharSequence
|
||||
|
||||
// if it is mapped to klass' parameter, then store it into map
|
||||
for (TypeProjection projection : substitution.get(parameter.getTypeConstructor())) {
|
||||
for (TypeProjection projection : substitution.get(parameter)) {
|
||||
// 1. projection = A
|
||||
// 2. projection = List<B>
|
||||
// 3. projection = Boolean
|
||||
|
||||
@@ -202,15 +202,12 @@ public class DeclarationsChecker {
|
||||
@NotNull ClassifierDescriptor classifierDescriptor,
|
||||
@NotNull PsiElement sourceElement
|
||||
) {
|
||||
Multimap<TypeConstructor, TypeProjection> multimap =
|
||||
Multimap<TypeParameterDescriptor, TypeProjection> multimap =
|
||||
SubstitutionUtils.buildDeepSubstitutionMultimap(classifierDescriptor.getDefaultType());
|
||||
for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
|
||||
for (Map.Entry<TypeParameterDescriptor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
|
||||
Collection<TypeProjection> projections = entry.getValue();
|
||||
if (projections.size() > 1) {
|
||||
TypeConstructor typeConstructor = entry.getKey();
|
||||
DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
|
||||
assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||
TypeParameterDescriptor typeParameterDescriptor = entry.getKey();
|
||||
|
||||
// Immediate arguments of supertypes cannot be projected
|
||||
Set<KotlinType> conflictingTypes = Sets.newLinkedHashSet();
|
||||
|
||||
@@ -21,8 +21,8 @@ import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -57,8 +57,8 @@ public class SubstitutionUtils {
|
||||
F declared in MyFooCollection -> out CharSequence
|
||||
*/
|
||||
@NotNull
|
||||
public static Multimap<TypeConstructor, TypeProjection> buildDeepSubstitutionMultimap(@NotNull KotlinType type) {
|
||||
Multimap<TypeConstructor, TypeProjection> fullSubstitution = LinkedHashMultimap.create();
|
||||
public static Multimap<TypeParameterDescriptor, TypeProjection> buildDeepSubstitutionMultimap(@NotNull KotlinType type) {
|
||||
Multimap<TypeParameterDescriptor, TypeProjection> fullSubstitution = LinkedHashMultimap.create();
|
||||
Map<TypeConstructor, TypeProjection> substitution = Maps.newHashMap();
|
||||
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitution);
|
||||
// we use the mutability of the map here
|
||||
@@ -71,7 +71,7 @@ public class SubstitutionUtils {
|
||||
@NotNull KotlinType context,
|
||||
@NotNull TypeSubstitutor substitutor,
|
||||
@NotNull Map<TypeConstructor, TypeProjection> substitution,
|
||||
@Nullable Multimap<TypeConstructor, TypeProjection> fullSubstitution
|
||||
@Nullable Multimap<TypeParameterDescriptor, TypeProjection> typeParameterMapping
|
||||
) {
|
||||
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
|
||||
List<TypeProjection> arguments = context.getArguments();
|
||||
@@ -87,13 +87,13 @@ public class SubstitutionUtils {
|
||||
TypeProjection substitute = substitutor.substitute(argument);
|
||||
assert substitute != null;
|
||||
substitution.put(parameter.getTypeConstructor(), substitute);
|
||||
if (fullSubstitution != null) {
|
||||
fullSubstitution.put(parameter.getTypeConstructor(), substitute);
|
||||
if (typeParameterMapping != null) {
|
||||
typeParameterMapping.put(parameter, substitute);
|
||||
}
|
||||
}
|
||||
if (KotlinBuiltIns.isNothingOrNullableNothing(context)) return;
|
||||
for (KotlinType supertype : context.getConstructor().getSupertypes()) {
|
||||
fillInDeepSubstitutor(supertype, substitutor, substitution, fullSubstitution);
|
||||
fillInDeepSubstitutor(supertype, substitutor, substitution, typeParameterMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user