IR: use map in remapTypeParameters
In LocalDeclarationLowering, the moved local function does not necessarily receive a continuous chunk of type parameters that it captures.
This commit is contained in:
@@ -215,33 +215,37 @@ fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) {
|
||||
|
||||
fun IrTypeParametersContainer.copyTypeParameters(
|
||||
srcTypeParameters: List<IrTypeParameter>,
|
||||
origin: IrDeclarationOrigin? = null
|
||||
origin: IrDeclarationOrigin? = null,
|
||||
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
|
||||
): List<IrTypeParameter> {
|
||||
val shift = typeParameters.size
|
||||
val oldToNewParameterMap = parameterMap.orEmpty().toMutableMap()
|
||||
// Any type parameter can figure in a boundary type for any other parameter.
|
||||
// Therefore, we first copy the parameters themselves, then set up their supertypes.
|
||||
val newTypeParameters = srcTypeParameters.mapIndexed { i, sourceParameter ->
|
||||
sourceParameter.copyToWithoutSuperTypes(this, index = i + shift, origin = origin ?: sourceParameter.origin)
|
||||
sourceParameter.copyToWithoutSuperTypes(this, index = i + shift, origin = origin ?: sourceParameter.origin).also {
|
||||
oldToNewParameterMap[sourceParameter] = it
|
||||
}
|
||||
}
|
||||
typeParameters.addAll(newTypeParameters)
|
||||
srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) ->
|
||||
dstParameter.copySuperTypesFrom(srcParameter)
|
||||
dstParameter.copySuperTypesFrom(srcParameter, oldToNewParameterMap)
|
||||
}
|
||||
return newTypeParameters
|
||||
}
|
||||
|
||||
fun IrTypeParametersContainer.copyTypeParametersFrom(
|
||||
source: IrTypeParametersContainer,
|
||||
origin: IrDeclarationOrigin? = null
|
||||
) = copyTypeParameters(source.typeParameters, origin)
|
||||
origin: IrDeclarationOrigin? = null,
|
||||
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
|
||||
) = copyTypeParameters(source.typeParameters, origin, parameterMap)
|
||||
|
||||
private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter) {
|
||||
private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter, srcToDstParameterMap: Map<IrTypeParameter, IrTypeParameter>) {
|
||||
val target = this
|
||||
val sourceParent = source.parent as IrTypeParametersContainer
|
||||
val targetParent = target.parent as IrTypeParametersContainer
|
||||
val shift = target.index - source.index
|
||||
source.superTypes.forEach {
|
||||
target.superTypes.add(it.remapTypeParameters(sourceParent, targetParent, shift))
|
||||
target.superTypes.add(it.remapTypeParameters(sourceParent, targetParent, srcToDstParameterMap))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,13 +312,24 @@ fun IrFunctionAccessExpression.passTypeArgumentsFrom(irFunction: IrTypeParameter
|
||||
Type parameters should correspond to the function where they are defined.
|
||||
`source` is where the type is originally taken from.
|
||||
*/
|
||||
fun IrType.remapTypeParameters(source: IrTypeParametersContainer, target: IrTypeParametersContainer, shift: Int = 0): IrType =
|
||||
fun IrType.remapTypeParameters(
|
||||
source: IrTypeParametersContainer,
|
||||
target: IrTypeParametersContainer,
|
||||
srcToDstParameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
|
||||
): IrType =
|
||||
when (this) {
|
||||
is IrSimpleType -> {
|
||||
val classifier = classifier.owner
|
||||
when {
|
||||
classifier is IrTypeParameter && classifier.parent == source ->
|
||||
IrSimpleTypeImpl(target.typeParameters[classifier.index + shift].symbol, hasQuestionMark, arguments, annotations)
|
||||
classifier is IrTypeParameter -> {
|
||||
val newClassifier =
|
||||
srcToDstParameterMap?.get(classifier) ?:
|
||||
if (classifier.parent == source)
|
||||
target.typeParameters[classifier.index]
|
||||
else
|
||||
classifier
|
||||
IrSimpleTypeImpl(newClassifier.symbol, hasQuestionMark, arguments, annotations)
|
||||
}
|
||||
|
||||
classifier is IrClass ->
|
||||
IrSimpleTypeImpl(
|
||||
@@ -323,7 +338,7 @@ fun IrType.remapTypeParameters(source: IrTypeParametersContainer, target: IrType
|
||||
arguments.map {
|
||||
when (it) {
|
||||
is IrTypeProjection -> makeTypeProjection(
|
||||
it.type.remapTypeParameters(source, target, shift),
|
||||
it.type.remapTypeParameters(source, target, srcToDstParameterMap),
|
||||
it.variance
|
||||
)
|
||||
else -> it
|
||||
|
||||
+1
-1
@@ -588,7 +588,7 @@ class LocalDeclarationsLowering(
|
||||
localFunctionContext.capturedTypeParameterToTypeParameter.putAll(
|
||||
capturedTypeParameters.zip(newTypeParameters)
|
||||
)
|
||||
newDeclaration.copyTypeParametersFrom(oldDeclaration)
|
||||
newDeclaration.copyTypeParametersFrom(oldDeclaration, parameterMap = localFunctionContext.capturedTypeParameterToTypeParameter)
|
||||
// Type parameters of oldDeclaration may depend on captured type parameters, so deal with that after copying.
|
||||
newDeclaration.typeParameters.drop(newTypeParameters.size).forEach { tp ->
|
||||
tp.superTypes.replaceAll { localFunctionContext.remapType(it) }
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
class Holder<T: Any>(val v: T)
|
||||
|
||||
fun <C: Any> outer(arg: C): C {
|
||||
fun <HC: Holder<C>> inner1(hh: HC): C {
|
||||
fun inner2() = hh.v // two type parameters: C and HC
|
||||
return inner2()
|
||||
}
|
||||
return inner1(Holder(arg))
|
||||
}
|
||||
|
||||
fun box(): String = outer("OK")
|
||||
+5
@@ -11797,6 +11797,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParametersInLocalFunction.kt")
|
||||
public void testTypeParametersInLocalFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+5
@@ -11797,6 +11797,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParametersInLocalFunction.kt")
|
||||
public void testTypeParametersInLocalFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+5
@@ -10647,6 +10647,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParametersInLocalFunction.kt")
|
||||
public void testTypeParametersInLocalFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+5
@@ -10647,6 +10647,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParametersInLocalFunction.kt")
|
||||
public void testTypeParametersInLocalFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Generated
+5
@@ -9182,6 +9182,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParametersInLocalFunction.kt")
|
||||
public void testTypeParametersInLocalFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+5
@@ -10257,6 +10257,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParametersInLocalFunction.kt")
|
||||
public void testTypeParametersInLocalFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/functions/bigArity")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user