From 049bb54ea6140de83c8ab8d89c1c2b68f0ed01f3 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Fri, 10 Jan 2020 20:49:23 +0300 Subject: [PATCH] IR: use map in remapTypeParameters In LocalDeclarationLowering, the moved local function does not necessarily receive a continuous chunk of type parameters that it captures. --- .../kotlin/backend/common/ir/IrUtils.kt | 39 +++++++++++++------ .../common/lower/LocalDeclarationsLowering.kt | 2 +- .../typeParametersInLocalFunction.kt | 13 +++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ 9 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index 06954b45790..fe05a6e7564 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -215,33 +215,37 @@ fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) { fun IrTypeParametersContainer.copyTypeParameters( srcTypeParameters: List, - origin: IrDeclarationOrigin? = null + origin: IrDeclarationOrigin? = null, + parameterMap: Map? = null ): List { 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? = null +) = copyTypeParameters(source.typeParameters, origin, parameterMap) -private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter) { +private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter, srcToDstParameterMap: Map) { 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? = 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 diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 7c597278e9c..52e7e4d368c 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -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) } diff --git a/compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt b/compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt new file mode 100644 index 00000000000..82332c0a633 --- /dev/null +++ b/compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt @@ -0,0 +1,13 @@ +// IGNORE_BACKEND_FIR: JVM_IR + +class Holder(val v: T) + +fun outer(arg: C): C { + fun > 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") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f0bc1d166cc..20649585a75 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8c3bf28d6bd..33690bedd7e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index c4b86aff4be..5ecfc6f4702 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -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) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 52312ad568a..833328084a2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 5af312a66e2..475adbebe8e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -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) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 0f7c1e23b33..7242c64ee52 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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)