KT-42151 fix type arguments in local class constructor reference types
This commit is contained in:
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -1078,18 +1077,37 @@ private fun makeKotlinType(
|
||||
classifier: IrClassifierSymbol,
|
||||
arguments: List<IrTypeArgument>,
|
||||
hasQuestionMark: Boolean
|
||||
): SimpleType = when (classifier) {
|
||||
is IrTypeParameterSymbol -> classifier.owner.toIrBasedDescriptor().defaultType
|
||||
is IrClassSymbol -> {
|
||||
val classDescriptor = classifier.owner.toIrBasedDescriptor()
|
||||
val kotlinTypeArguments = arguments.mapIndexed { index, it ->
|
||||
when (it) {
|
||||
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType())
|
||||
is IrStarProjection -> StarProjectionImpl(classDescriptor.typeConstructor.parameters[index])
|
||||
else -> error(it)
|
||||
): SimpleType =
|
||||
when (classifier) {
|
||||
is IrTypeParameterSymbol -> classifier.owner.toIrBasedDescriptor().defaultType
|
||||
is IrClassSymbol -> {
|
||||
val classDescriptor = classifier.owner.toIrBasedDescriptor()
|
||||
val kotlinTypeArguments = arguments.mapIndexed { index, it ->
|
||||
when (it) {
|
||||
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toIrBasedKotlinType())
|
||||
is IrStarProjection -> StarProjectionImpl(classDescriptor.typeConstructor.parameters[index])
|
||||
else -> error(it)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
classDescriptor.defaultType.replace(newArguments = kotlinTypeArguments).makeNullableAsSpecified(hasQuestionMark)
|
||||
} catch (e: Throwable) {
|
||||
throw RuntimeException(
|
||||
"Classifier: $classDescriptor\n" +
|
||||
"Type parameters:\n" +
|
||||
classDescriptor.defaultType.constructor.parameters.withIndex()
|
||||
.joinToString(separator = "\n") {
|
||||
"${it.index}: ${(it.value as IrBasedTypeParameterDescriptor).owner.render()}"
|
||||
} +
|
||||
"\nType arguments:\n" +
|
||||
arguments.withIndex()
|
||||
.joinToString(separator = "\n") {
|
||||
"${it.index}: ${it.value.render()}"
|
||||
},
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
classDescriptor.defaultType.replace(newArguments = kotlinTypeArguments).makeNullableAsSpecified(hasQuestionMark)
|
||||
else -> error("unknown classifier kind $classifier")
|
||||
}
|
||||
else -> error("unknown classifier kind $classifier")
|
||||
}
|
||||
|
||||
@@ -390,9 +390,9 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
||||
}
|
||||
}
|
||||
|
||||
fun extractTypeParameters(klass: IrDeclarationParent): List<IrTypeParameter> {
|
||||
fun extractTypeParameters(parent: IrDeclarationParent): List<IrTypeParameter> {
|
||||
val result = mutableListOf<IrTypeParameter>()
|
||||
var current: IrDeclarationParent? = klass
|
||||
var current: IrDeclarationParent? = parent
|
||||
while (current != null) {
|
||||
(current as? IrTypeParametersContainer)?.let { result += it.typeParameters }
|
||||
current =
|
||||
@@ -404,9 +404,11 @@ fun extractTypeParameters(klass: IrDeclarationParent): List<IrTypeParameter> {
|
||||
else -> null
|
||||
}
|
||||
is IrConstructor -> current.parent as IrClass
|
||||
is IrFunction -> if (current.visibility == DescriptorVisibilities.LOCAL || current.dispatchReceiverParameter != null) {
|
||||
current.parent
|
||||
} else null
|
||||
is IrFunction ->
|
||||
if (current.visibility == DescriptorVisibilities.LOCAL || current.dispatchReceiverParameter != null)
|
||||
current.parent
|
||||
else
|
||||
null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.types
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isPropertyAccessor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
@@ -155,13 +157,28 @@ val IrClassSymbol.starProjectedType: IrSimpleType
|
||||
)
|
||||
|
||||
val IrClass.typeConstructorParameters: Sequence<IrTypeParameter>
|
||||
get() = generateSequence(this as IrTypeParametersContainer,
|
||||
{ current ->
|
||||
val parent = current.parent as? IrTypeParametersContainer
|
||||
if (parent is IrClass && current is IrClass && !current.isInner) null
|
||||
else parent
|
||||
})
|
||||
.flatMap { it.typeParameters }
|
||||
get() =
|
||||
generateSequence(
|
||||
this as IrTypeParametersContainer,
|
||||
{ current ->
|
||||
val parent = current.parent as? IrTypeParametersContainer
|
||||
when {
|
||||
parent is IrSimpleFunction && parent.isPropertyAccessor -> {
|
||||
// KT-42151
|
||||
// Property type parameters for local classes declared inside property accessors are not captured in FE descriptors.
|
||||
// In order to match type parameters against type arguments in IR types translated from KotlinTypes,
|
||||
// we should stop on property accessor here.
|
||||
// NB this can potentially cause problems with inline properties with reified type parameters.
|
||||
// Ideally this should be fixed in FE.
|
||||
null
|
||||
}
|
||||
parent is IrClass && current is IrClass && !current.isInner ->
|
||||
null
|
||||
else ->
|
||||
parent
|
||||
}
|
||||
}
|
||||
).flatMap { it.typeParameters }
|
||||
|
||||
fun IrClassifierSymbol.typeWithParameters(parameters: List<IrTypeParameter>): IrSimpleType =
|
||||
typeWith(parameters.map { it.defaultType })
|
||||
|
||||
@@ -526,7 +526,16 @@ fun IrMemberAccessExpression<*>.getTypeSubstitutionMap(irFunction: IrFunction):
|
||||
|
||||
val result = mutableMapOf<IrTypeParameterSymbol, IrType>()
|
||||
if (dispatchReceiverTypeArguments.isNotEmpty()) {
|
||||
val parentTypeParameters = extractTypeParameters(irFunction.parentClassOrNull!!)
|
||||
val parentTypeParameters =
|
||||
if (irFunction is IrConstructor) {
|
||||
val constructedClass = irFunction.parentAsClass
|
||||
if (!constructedClass.isInner && dispatchReceiver != null) {
|
||||
throw AssertionError("Non-inner class constructor reference with dispatch receiver:\n${this.dump()}")
|
||||
}
|
||||
extractTypeParameters(constructedClass.parent as IrClass)
|
||||
} else {
|
||||
extractTypeParameters(irFunction.parentClassOrNull!!)
|
||||
}
|
||||
parentTypeParameters.withIndex().forEach { (index, typeParam) ->
|
||||
dispatchReceiverTypeArguments[index].typeOrNull?.let {
|
||||
result[typeParam.symbol] = it
|
||||
|
||||
Reference in New Issue
Block a user