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:
Denis Zharkov
2015-11-06 12:06:01 +03:00
parent 188bcf0a03
commit daed74f9b2
3 changed files with 12 additions and 15 deletions
@@ -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);
}
}
}