Refactoring: Improve createExpectActualTypeParameterSubstitutor API
Review: https://jetbrains.team/p/kt/reviews/12279/files Motivation: make sure that cases like KT-62027 won't happen again Review: https://jetbrains.team/p/kt/reviews/12279/files Now it's responsibility of the `createExpectActualTypeParameterSubstitutor` calller to think about the case when parameters size isn't equal. You must not be able to create a substitutor if type parameters sizes are not equal Improvement in `createExpectActualTypeParameterSubstitutor` API also improves `AbstractExpectActualCompatibilityChecker.getCallablesCompatibility` API. Because suppose that you accidentally created a redundant wrapping substitutor => you need to handle the case of not equal type parameters size on the call site => you start thinking why you should do that on the call site? It must be a responsibility of `getCallablesCompatibility` => you realize that you created a redundant wrapping substitutor
This commit is contained in:
+5
-9
@@ -37,8 +37,6 @@ import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||
|
||||
internal abstract class IrExpectActualMatchingContext(
|
||||
@@ -238,16 +236,14 @@ internal abstract class IrExpectActualMatchingContext(
|
||||
override val PropertySymbolMarker.setter: FunctionSymbolMarker?
|
||||
get() = asIr().setter?.symbol
|
||||
|
||||
@OptIn(UnsafeCastFunction::class)
|
||||
override fun createExpectActualTypeParameterSubstitutor(
|
||||
expectTypeParameters: List<TypeParameterSymbolMarker>,
|
||||
actualTypeParameters: List<TypeParameterSymbolMarker>,
|
||||
expectActualTypeParameters: List<Pair<TypeParameterSymbolMarker, TypeParameterSymbolMarker>>,
|
||||
parentSubstitutor: TypeSubstitutorMarker?,
|
||||
): TypeSubstitutorMarker {
|
||||
val expectParameters = expectTypeParameters.castAll<IrTypeParameterSymbol>()
|
||||
val actualParameters = actualTypeParameters.castAll<IrTypeParameterSymbol>()
|
||||
val actualTypes = actualParameters.map { it.owner.defaultType }
|
||||
val substitutor = IrTypeSubstitutor(expectParameters, actualTypes, allowEmptySubstitution = true)
|
||||
val typeParametersToArguments = expectActualTypeParameters.associate { (expect, actual) ->
|
||||
(expect as IrTypeParameterSymbol) to (actual as IrTypeParameterSymbol).owner.defaultType
|
||||
}
|
||||
val substitutor = IrTypeSubstitutor(typeParametersToArguments, allowEmptySubstitution = true)
|
||||
return when (parentSubstitutor) {
|
||||
null -> substitutor
|
||||
is AbstractIrTypeSubstitutor -> IrChainedSubstitutor(parentSubstitutor, substitutor)
|
||||
|
||||
+3
-5
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeArgument
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeSubstitutor
|
||||
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
|
||||
@@ -50,11 +51,8 @@ class WrapInlineDeclarationsWithReifiedTypeParametersLowering(val context: Backe
|
||||
if (!owner.isInlineFunWithReifiedParameter()) {
|
||||
return expression
|
||||
}
|
||||
val substitutionMap = expression.typeSubstitutionMap.entries
|
||||
val typeSubstitutor = IrTypeSubstitutor(
|
||||
substitutionMap.map { it.key },
|
||||
substitutionMap.map { it.value as IrTypeArgument },
|
||||
)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val typeSubstitutor = IrTypeSubstitutor(expression.typeSubstitutionMap as Map<IrTypeParameterSymbol, IrTypeArgument>)
|
||||
|
||||
val function = irFactory.buildFun {
|
||||
name = Name.identifier("${owner.name}${"$"}wrap")
|
||||
|
||||
@@ -65,12 +65,15 @@ abstract class BaseIrTypeSubstitutor : AbstractIrTypeSubstitutor() {
|
||||
}
|
||||
|
||||
class IrTypeSubstitutor(
|
||||
typeParameters: List<IrTypeParameterSymbol>,
|
||||
typeArguments: List<IrTypeArgument>,
|
||||
private val allowEmptySubstitution: Boolean = false,
|
||||
private val substitution: Map<IrTypeParameterSymbol, IrTypeArgument>,
|
||||
private val allowEmptySubstitution: Boolean = false
|
||||
) : BaseIrTypeSubstitutor() {
|
||||
init {
|
||||
assert(typeParameters.size == typeArguments.size) {
|
||||
constructor(
|
||||
typeParameters: List<IrTypeParameterSymbol>,
|
||||
typeArguments: List<IrTypeArgument>,
|
||||
allowEmptySubstitution: Boolean = false,
|
||||
) : this(typeParameters.zip(typeArguments).toMap(), allowEmptySubstitution) {
|
||||
check(typeParameters.size == typeArguments.size) {
|
||||
"Unexpected number of type arguments: ${typeArguments.size}\n" +
|
||||
"Type parameters are:\n" +
|
||||
typeParameters.joinToString(separator = "\n") { it.owner.render() } +
|
||||
@@ -79,8 +82,6 @@ class IrTypeSubstitutor(
|
||||
}
|
||||
}
|
||||
|
||||
private val substitution = typeParameters.zip(typeArguments).toMap()
|
||||
|
||||
override fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument =
|
||||
substitution[typeParameter]
|
||||
?: typeParameter.takeIf { allowEmptySubstitution }?.owner?.defaultType
|
||||
|
||||
@@ -595,17 +595,12 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
||||
}
|
||||
|
||||
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker {
|
||||
val typeParameters = mutableListOf<IrTypeParameterSymbol>()
|
||||
val typeArguments = mutableListOf<IrTypeArgument>()
|
||||
for ((key, value) in map) {
|
||||
typeParameters += key as IrTypeParameterSymbol
|
||||
typeArguments += value as IrTypeArgument
|
||||
}
|
||||
return IrTypeSubstitutor(typeParameters, typeArguments)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return IrTypeSubstitutor(map as Map<IrTypeParameterSymbol, IrTypeArgument>)
|
||||
}
|
||||
|
||||
override fun createEmptySubstitutor(): TypeSubstitutorMarker {
|
||||
return IrTypeSubstitutor(emptyList(), emptyList())
|
||||
return IrTypeSubstitutor(emptyMap())
|
||||
}
|
||||
|
||||
override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
|
||||
+3
-5
@@ -208,8 +208,6 @@ class IrBodyDeserializer(
|
||||
return IrSimpleTypeBuilder().apply { classifier = klass.symbol }.buildSimpleType()
|
||||
}
|
||||
|
||||
val typeArguments = ArrayList<IrTypeArgument>(typeParameters.size)
|
||||
val typeParameterSymbols = ArrayList<IrTypeParameterSymbol>(typeParameters.size)
|
||||
val rawType = with(IrSimpleTypeBuilder()) {
|
||||
arguments = typeParameters.memoryOptimizedMap {
|
||||
classifier = it.symbol
|
||||
@@ -219,15 +217,15 @@ class IrBodyDeserializer(
|
||||
buildSimpleType()
|
||||
}
|
||||
|
||||
val typeParametersToArguments = HashMap<IrTypeParameterSymbol, IrTypeArgument>(typeParameters.size)
|
||||
for (i in typeParameters.indices) {
|
||||
val typeParameter = typeParameters[i]
|
||||
val callTypeArgument = constructorCall.getTypeArgument(i) ?: error("No type argument for id $i")
|
||||
val typeArgument = makeTypeProjection(callTypeArgument, typeParameter.variance)
|
||||
typeArguments.add(typeArgument)
|
||||
typeParameterSymbols.add(typeParameter.symbol)
|
||||
typeParametersToArguments[typeParameter.symbol] = typeArgument
|
||||
}
|
||||
|
||||
val substitutor = IrTypeSubstitutor(typeParameterSymbols, typeArguments)
|
||||
val substitutor = IrTypeSubstitutor(typeParametersToArguments)
|
||||
return substitutor.substitute(rawType) as IrSimpleType
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user