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(
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
@@ -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")
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)