Underlying constructor for type alias should always be substituted

Otherwise PSI2IR fails because of type mismatch.
This commit is contained in:
Dmitry Petrov
2018-03-16 17:11:24 +03:00
parent bfcf1584a2
commit eb5904ea8e
8 changed files with 81 additions and 15 deletions
@@ -599,6 +599,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
final TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
unsubstitutedTypeParameters, configuration.substitution, substitutedDescriptor, substitutedTypeParameters, wereChanges
);
if (substitutor == null) return null;
KotlinType substitutedReceiverParameterType = null;
if (configuration.newExtensionReceiverParameterType != null) {
@@ -768,6 +769,15 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
return visitor.visitFunctionDescriptor(this, data);
}
@Nullable
public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
FunctionDescriptor substitutedDescriptor,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull TypeSubstitutor substitutor
) {
return getSubstitutedValueParameters(substitutedDescriptor, unsubstitutedValueParameters, substitutor, false, false, null);
}
@Nullable
public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
FunctionDescriptor substitutedDescriptor,
@@ -175,27 +175,26 @@ class TypeAliasConstructorDescriptorImpl private constructor(
constructor: ClassConstructorDescriptor
): TypeAliasConstructorDescriptor? {
val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?: return null
val substitutedConstructor = constructor.substitute(substitutorForUnderlyingClass) ?: return null
val typeAliasConstructor =
TypeAliasConstructorDescriptorImpl(
storageManager, typeAliasDescriptor, constructor, null, constructor.annotations,
storageManager, typeAliasDescriptor,
substitutedConstructor,
null, constructor.annotations,
constructor.kind, typeAliasDescriptor.source
)
val valueParameters =
FunctionDescriptorImpl.getSubstitutedValueParameters(
typeAliasConstructor, constructor.valueParameters, substitutorForUnderlyingClass, false, false,
null
typeAliasConstructor, constructor.valueParameters, substitutorForUnderlyingClass
) ?: return null
val returnType = run {
val returnTypeNoAbbreviation = substitutorForUnderlyingClass.substitute(constructor.returnType, Variance.INVARIANT)
?: return null
returnTypeNoAbbreviation.unwrap().lowerIfFlexible().withAbbreviation(typeAliasDescriptor.defaultType)
}
val returnType = substitutedConstructor.returnType.unwrap().lowerIfFlexible().withAbbreviation(typeAliasDescriptor.defaultType)
val receiverParameterType =
constructor.dispatchReceiverParameter?.let { substitutorForUnderlyingClass.safeSubstitute(it.type, Variance.INVARIANT) }
val receiverParameterType = constructor.dispatchReceiverParameter?.let {
substitutorForUnderlyingClass.safeSubstitute(it.type, Variance.INVARIANT)
}
typeAliasConstructor.initialize(
receiverParameterType,
@@ -40,10 +40,12 @@ public class DescriptorSubstitutor {
@NotNull DeclarationDescriptor newContainingDeclaration,
@NotNull @Mutable List<TypeParameterDescriptor> result
) {
return substituteTypeParameters(typeParameters, originalSubstitution, newContainingDeclaration, result, null);
TypeSubstitutor substitutor = substituteTypeParameters(typeParameters, originalSubstitution, newContainingDeclaration, result, null);
if (substitutor == null) throw new AssertionError("Substitution failed");
return substitutor;
}
@NotNull
@Nullable
public static TypeSubstitutor substituteTypeParameters(
@ReadOnly @NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull TypeSubstitution originalSubstitution,
@@ -80,7 +82,7 @@ public class DescriptorSubstitutor {
TypeParameterDescriptorImpl substituted = substitutedMap.get(descriptor);
for (KotlinType upperBound : descriptor.getUpperBounds()) {
KotlinType substitutedBound = substitutor.substitute(upperBound, Variance.IN_VARIANCE);
assert substitutedBound != null : "Upper bound failed to substitute: " + descriptor;
if (substitutedBound == null) return null;
if (substitutedBound != upperBound && wereChanges != null) {
wereChanges[0] = true;