From 332b191546eedacce24c7deb52f10c54af420703 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Sun, 14 Apr 2019 18:59:25 +0300 Subject: [PATCH] Fix ir type substitutor --- .../kotlin/ir/types/IrTypeSubstitutor.kt | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt index 6cfe36cd32f..c5fa768caa6 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt @@ -7,10 +7,8 @@ package org.jetbrains.kotlin.ir.types import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol -import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl -import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection -import org.jetbrains.kotlin.ir.types.impl.originalKotlinType -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.ir.types.impl.* +import org.jetbrains.kotlin.types.TypeSubstitutor class IrTypeSubstitutor( @@ -20,44 +18,53 @@ class IrTypeSubstitutor( ) { private val substitution = typeParameters.zip(typeArguments).toMap() - fun substitute(type: IrType) = if (substitution.isNotEmpty()) doSubstituteType(type) else type + private fun IrType.typeParameterConstructor(): IrTypeParameterSymbol? { + return if (this is IrSimpleType) classifier as? IrTypeParameterSymbol + else null + } - private fun doSubstituteTypeArgument(typeArgument: IrTypeArgument): IrTypeArgument { + fun substitute(type: IrType): IrType { + if (substitution.isEmpty()) return type + + return type.typeParameterConstructor()?.let { + val typeArgument = substitution.getValue(it) + when (typeArgument) { + is IrStarProjection -> irBuiltIns.anyNType + is IrTypeProjection -> typeArgument.type + else -> error("unknown type argument") + } + } ?: substituteType(type) + } + + private fun substituteType(irType: IrType): IrType { + return when (irType) { + is IrDynamicType -> irType + is IrErrorType -> irType + else -> { + require(irType is IrSimpleType) + with(irType.toBuilder()) { + arguments = irType.arguments.map { substituteTypeArgument(it) } + buildSimpleType() + } + } + } + } + + private fun substituteTypeArgument(typeArgument: IrTypeArgument): IrTypeArgument { if (typeArgument is IrStarProjection) return typeArgument require(typeArgument is IrTypeProjection) - return if (typeArgument is IrSimpleType) { - val classifier = typeArgument.classifier - if (classifier is IrTypeParameterSymbol) substitution.getValue(classifier) - else { - makeTypeProjection(doSubstituteType(typeArgument), Variance.INVARIANT) - } - } else makeTypeProjection(doSubstituteType(typeArgument.type), typeArgument.variance) - } - - private fun doSubstituteType(type: IrType): IrType = when (type) { - is IrErrorType -> type - is IrDynamicType -> type - is IrSimpleType -> { + val type = typeArgument.type + if (type is IrSimpleType) { val classifier = type.classifier if (classifier is IrTypeParameterSymbol) { - val argument = substitution.getValue(classifier) - if (argument is IrTypeProjection) { - argument.type - } else irBuiltIns.anyNType // StarProjection - } else { - type.run { - IrSimpleTypeImpl( - originalKotlinType, - classifier, - hasQuestionMark, - arguments.map { doSubstituteTypeArgument(it) }, - annotations - ) - } + val newArgument = substitution.getValue(classifier) + return if (newArgument is IrTypeProjection) { + makeTypeProjection(newArgument.type, TypeSubstitutor.combine(typeArgument.variance, newArgument.variance)) + } else newArgument } } - else -> error("Unknown type") + return makeTypeProjection(substituteType(typeArgument.type), typeArgument.variance) } }