diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt index 9d8633a0ebb..32b256aa268 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt @@ -247,7 +247,7 @@ internal abstract class IrExpectActualMatchingContext( val expectParameters = expectTypeParameters.castAll() val actualParameters = actualTypeParameters.castAll() val actualTypes = actualParameters.map { it.owner.defaultType } - val substitutor = IrTypeSubstitutor(expectParameters, actualTypes, typeContext.irBuiltIns, allowEmptySubstitution = true) + val substitutor = IrTypeSubstitutor(expectParameters, actualTypes, allowEmptySubstitution = true) return when (parentSubstitutor) { null -> substitutor is AbstractIrTypeSubstitutor -> IrChainedSubstitutor(parentSubstitutor, substitutor) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/WrapInlineDeclarationsWithReifiedTypeParametersLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/WrapInlineDeclarationsWithReifiedTypeParametersLowering.kt index 4387383a6a4..0f5e0b2bd32 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/WrapInlineDeclarationsWithReifiedTypeParametersLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/WrapInlineDeclarationsWithReifiedTypeParametersLowering.kt @@ -50,15 +50,10 @@ class WrapInlineDeclarationsWithReifiedTypeParametersLowering(val context: Backe if (!owner.isInlineFunWithReifiedParameter()) { return expression } - val substitutionMap = expression.typeSubstitutionMap - .entries - .map { (key, value) -> - key to (value as IrTypeArgument) - } + val substitutionMap = expression.typeSubstitutionMap.entries val typeSubstitutor = IrTypeSubstitutor( - substitutionMap.map { it.first }, - substitutionMap.map { it.second }, - context.irBuiltIns + substitutionMap.map { it.key }, + substitutionMap.map { it.value as IrTypeArgument }, ) val function = irFactory.buildFun { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt index d5b62fd4f60..278c4fa6676 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt @@ -233,10 +233,6 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont throw AssertionError("Simple type expected: ${irType.render()}") val irClassSymbol = irType.classOrNull ?: throw AssertionError("Class type expected: ${irType.render()}") - return IrTypeSubstitutor( - irClassSymbol.owner.typeParameters.map { it.symbol }, - irType.arguments, - jvmContext.irBuiltIns - ) + return IrTypeSubstitutor(irClassSymbol.owner.typeParameters.map { it.symbol }, irType.arguments) } } 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 90b6496fef6..517909ff53e 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 @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.ir.types -import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.impl.* -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker import org.jetbrains.kotlin.utils.memoryOptimizedMap @@ -17,60 +17,58 @@ abstract class AbstractIrTypeSubstitutor : TypeSubstitutorMarker { abstract fun substitute(type: IrType): IrType } -abstract class BaseIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : AbstractIrTypeSubstitutor() { - - private fun IrType.typeParameterConstructor(): IrTypeParameterSymbol? { - return if (this is IrSimpleType) classifier as? IrTypeParameterSymbol - else null - } - +abstract class BaseIrTypeSubstitutor : AbstractIrTypeSubstitutor() { abstract fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument abstract fun isEmptySubstitution(): Boolean final override fun substitute(type: IrType): IrType { if (isEmptySubstitution()) return type - return substituteType(type) + return when (val result = substituteType(type)) { + is IrStarProjection -> error("Cannot replace top-level type with star projection: ${type.render()}") + is IrTypeProjection -> result.type + } } - private fun substituteType(irType: IrType): IrType { - val substitutedTypeParameter = irType.typeParameterConstructor()?.let { - when (val typeArgument = getSubstitutionArgument(it)) { - is IrStarProjection -> irBuiltIns.anyNType // TODO upper bound for T - is IrTypeProjection -> typeArgument.type.mergeNullability(irType) - .addAnnotations(irType.annotations) + private fun substituteType(irType: IrType): IrTypeArgument { + val classifier = (irType as? IrSimpleType)?.classifier + if (classifier is IrTypeParameterSymbol) { + return when (val typeArgument = getSubstitutionArgument(classifier)) { + is IrStarProjection -> typeArgument + is IrTypeProjection -> makeTypeProjection( + typeArgument.type.mergeNullability(irType).addAnnotations(irType.annotations), + typeArgument.variance, + ) } } - if (substitutedTypeParameter != null) { - return substitutedTypeParameter - } return when (irType) { is IrSimpleType -> with(irType.toBuilder()) { arguments = irType.arguments.memoryOptimizedMap { substituteTypeArgument(it) } buildSimpleType() } - is IrDynamicType, - is IrErrorType -> irType + is IrDynamicType, is IrErrorType -> makeTypeProjection(irType, Variance.INVARIANT) else -> error("Unexpected type: $irType") } } - private fun substituteTypeArgument(typeArgument: IrTypeArgument): IrTypeArgument { - return when (typeArgument) { + private fun substituteTypeArgument(typeArgument: IrTypeArgument): IrTypeArgument = + when (typeArgument) { is IrStarProjection -> typeArgument - is IrTypeProjection -> makeTypeProjection(substituteType(typeArgument.type), typeArgument.variance) + is IrTypeProjection -> when (val replacement = substituteType(typeArgument.type)) { + is IrStarProjection -> replacement + is IrTypeProjection -> makeTypeProjection( + replacement.type, TypeSubstitutor.combine(typeArgument.variance, replacement.variance) + ) + } } - } } class IrTypeSubstitutor( typeParameters: List, typeArguments: List, - irBuiltIns: IrBuiltIns, - private val allowEmptySubstitution: Boolean = false -) : BaseIrTypeSubstitutor(irBuiltIns) { - + private val allowEmptySubstitution: Boolean = false, +) : BaseIrTypeSubstitutor() { init { assert(typeParameters.size == typeArguments.size) { "Unexpected number of type arguments: ${typeArguments.size}\n" + @@ -95,9 +93,7 @@ class IrCapturedTypeSubstitutor( typeParameters: List, typeArguments: List, capturedTypes: List, - irBuiltIns: IrBuiltIns -) : BaseIrTypeSubstitutor(irBuiltIns) { - +) : BaseIrTypeSubstitutor() { init { assert(typeArguments.size == typeParameters.size) assert(capturedTypes.size == typeParameters.size) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index 5f4463887ca..345459b306b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -276,7 +276,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon val newArguments = ArrayList(typeArguments.size) - val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.memoryOptimizedMap { it.symbol }, typeArguments, capturedTypes, irBuiltIns) + val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.memoryOptimizedMap { it.symbol }, typeArguments, capturedTypes) for (index in typeArguments.indices) { val oldArgument = typeArguments[index] @@ -498,7 +498,6 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon IrTypeSubstitutor( (this as IrType).getClass()!!.typeParameters.memoryOptimizedMap { it.symbol }, (this as? IrSimpleType)?.arguments.orEmpty(), - irBuiltIns ).substitute(type as IrType) } @@ -581,7 +580,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun substitutionSupertypePolicy(type: SimpleTypeMarker): TypeCheckerState.SupertypesPolicy { require(type is IrSimpleType) val parameters = extractTypeParameters((type.classifier as IrClassSymbol).owner).memoryOptimizedMap { it.symbol } - val typeSubstitutor = IrTypeSubstitutor(parameters, type.arguments, irBuiltIns) + val typeSubstitutor = IrTypeSubstitutor(parameters, type.arguments) return object : TypeCheckerState.SupertypesPolicy.DoCustomTransform() { override fun transformType(state: TypeCheckerState, type: KotlinTypeMarker): SimpleTypeMarker { @@ -602,11 +601,11 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon typeParameters += key as IrTypeParameterSymbol typeArguments += value as IrTypeArgument } - return IrTypeSubstitutor(typeParameters, typeArguments, irBuiltIns) + return IrTypeSubstitutor(typeParameters, typeArguments) } override fun createEmptySubstitutor(): TypeSubstitutorMarker { - return IrTypeSubstitutor(emptyList(), emptyList(), irBuiltIns) + return IrTypeSubstitutor(emptyList(), emptyList()) } override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker { diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt index d54bc4d4466..b21345d3061 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt @@ -23,8 +23,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.* -import org.jetbrains.kotlin.utils.memoryOptimizedMap import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.utils.memoryOptimizedMap import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody import org.jetbrains.kotlin.backend.common.serialization.proto.IrBranch as ProtoBranch @@ -193,8 +193,7 @@ class IrBodyDeserializer( // TODO: probably a bit more abstraction possible here up to `IrMemberAccessExpression` // but at this point further complexization looks overengineered - private class IrAnnotationType(private val builtIns: IrBuiltIns) : IrDelegatedSimpleType() { - + private class IrAnnotationType : IrDelegatedSimpleType() { var irConstructorCall: IrConstructorCall? = null override val delegate: IrSimpleType by lazy { resolveType() } @@ -228,13 +227,13 @@ class IrBodyDeserializer( typeParameterSymbols.add(typeParameter.symbol) } - val substitutor = IrTypeSubstitutor(typeParameterSymbols, typeArguments, builtIns) + val substitutor = IrTypeSubstitutor(typeParameterSymbols, typeArguments) return substitutor.substitute(rawType) as IrSimpleType } } fun deserializeAnnotation(proto: ProtoConstructorCall): IrConstructorCall { - val irType = IrAnnotationType(builtIns) + val irType = IrAnnotationType() // TODO: use real coordinates return deserializeConstructorCall(proto, 0, 0, irType).also { irType.irConstructorCall = it } }