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(
|
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
|
||||||
|
|||||||
+1
-1
@@ -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")
|
||||||
+5
@@ -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)
|
||||||
|
|||||||
+5
@@ -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)
|
||||||
|
|||||||
+5
@@ -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)
|
||||||
|
|||||||
+5
@@ -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)
|
||||||
|
|||||||
Generated
+5
@@ -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)
|
||||||
|
|||||||
+5
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user