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:
Georgy Bronnikov
2020-01-10 20:49:23 +03:00
parent 0abdd0cb7b
commit 049bb54ea6
9 changed files with 71 additions and 13 deletions
@@ -215,33 +215,37 @@ fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) {
fun IrTypeParametersContainer.copyTypeParameters( fun IrTypeParametersContainer.copyTypeParameters(
srcTypeParameters: List<IrTypeParameter>, srcTypeParameters: List<IrTypeParameter>,
origin: IrDeclarationOrigin? = null origin: IrDeclarationOrigin? = null,
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
): List<IrTypeParameter> { ): List<IrTypeParameter> {
val shift = typeParameters.size val shift = typeParameters.size
val oldToNewParameterMap = parameterMap.orEmpty().toMutableMap()
// Any type parameter can figure in a boundary type for any other parameter. // 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. // Therefore, we first copy the parameters themselves, then set up their supertypes.
val newTypeParameters = srcTypeParameters.mapIndexed { i, sourceParameter -> 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) typeParameters.addAll(newTypeParameters)
srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) -> srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) ->
dstParameter.copySuperTypesFrom(srcParameter) dstParameter.copySuperTypesFrom(srcParameter, oldToNewParameterMap)
} }
return newTypeParameters return newTypeParameters
} }
fun IrTypeParametersContainer.copyTypeParametersFrom( fun IrTypeParametersContainer.copyTypeParametersFrom(
source: IrTypeParametersContainer, source: IrTypeParametersContainer,
origin: IrDeclarationOrigin? = null origin: IrDeclarationOrigin? = null,
) = copyTypeParameters(source.typeParameters, origin) 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 target = this
val sourceParent = source.parent as IrTypeParametersContainer val sourceParent = source.parent as IrTypeParametersContainer
val targetParent = target.parent as IrTypeParametersContainer val targetParent = target.parent as IrTypeParametersContainer
val shift = target.index - source.index
source.superTypes.forEach { 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. Type parameters should correspond to the function where they are defined.
`source` is where the type is originally taken from. `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) { when (this) {
is IrSimpleType -> { is IrSimpleType -> {
val classifier = classifier.owner val classifier = classifier.owner
when { when {
classifier is IrTypeParameter && classifier.parent == source -> classifier is IrTypeParameter -> {
IrSimpleTypeImpl(target.typeParameters[classifier.index + shift].symbol, hasQuestionMark, arguments, annotations) val newClassifier =
srcToDstParameterMap?.get(classifier) ?:
if (classifier.parent == source)
target.typeParameters[classifier.index]
else
classifier
IrSimpleTypeImpl(newClassifier.symbol, hasQuestionMark, arguments, annotations)
}
classifier is IrClass -> classifier is IrClass ->
IrSimpleTypeImpl( IrSimpleTypeImpl(
@@ -323,7 +338,7 @@ fun IrType.remapTypeParameters(source: IrTypeParametersContainer, target: IrType
arguments.map { arguments.map {
when (it) { when (it) {
is IrTypeProjection -> makeTypeProjection( is IrTypeProjection -> makeTypeProjection(
it.type.remapTypeParameters(source, target, shift), it.type.remapTypeParameters(source, target, srcToDstParameterMap),
it.variance it.variance
) )
else -> it else -> it
@@ -588,7 +588,7 @@ class LocalDeclarationsLowering(
localFunctionContext.capturedTypeParameterToTypeParameter.putAll( localFunctionContext.capturedTypeParameterToTypeParameter.putAll(
capturedTypeParameters.zip(newTypeParameters) 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. // Type parameters of oldDeclaration may depend on captured type parameters, so deal with that after copying.
newDeclaration.typeParameters.drop(newTypeParameters.size).forEach { tp -> newDeclaration.typeParameters.drop(newTypeParameters.size).forEach { tp ->
tp.superTypes.replaceAll { localFunctionContext.remapType(it) } 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")
@@ -11797,6 +11797,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); 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") @TestMetadata("compiler/testData/codegen/box/functions/bigArity")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -11797,6 +11797,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); 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") @TestMetadata("compiler/testData/codegen/box/functions/bigArity")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -10647,6 +10647,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); 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") @TestMetadata("compiler/testData/codegen/box/functions/bigArity")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -10647,6 +10647,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); 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") @TestMetadata("compiler/testData/codegen/box/functions/bigArity")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -9182,6 +9182,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); 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") @TestMetadata("compiler/testData/codegen/box/functions/bigArity")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -10257,6 +10257,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); 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") @TestMetadata("compiler/testData/codegen/box/functions/bigArity")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)