From 1222b72dcdaf20080c416f145495a93748ce5875 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 12 Jan 2021 19:23:13 +0500 Subject: [PATCH] [IR] Fix for https://youtrack.jetbrains.com/issue/KT-44219 + test --- .../backend/konan/lower/PostInlineLowering.kt | 50 ++++++++++++------- .../lower/SpecialBackendChecksTraversal.kt | 3 +- .../tests/codegen/ktype/nonReified.kt | 10 ++++ .../tests/compilerChecks/t59.kt | 2 +- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt index c20174f7938..bd4ad0a2dc3 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt @@ -5,35 +5,46 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.ir.Symbols -import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.renderCompilerError -import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.util.file import org.jetbrains.kotlin.ir.util.irCall -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer /** * This pass runs after inlining and performs the following additional transformations over some operations: * - Convert immutableBlobOf() arguments to special IrConst. * - Convert `obj::class` and `Class::class` to calls. */ -internal class PostInlineLowering(val context: Context) : FileLoweringPass { +internal class PostInlineLowering(val context: Context) : BodyLoweringPass { private val symbols get() = context.ir.symbols - override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(object : IrBuildingTransformer(context) { + override fun lower(irBody: IrBody, container: IrDeclaration) { + val irFile = container.file + irBody.transformChildren(object : IrElementTransformer { + override fun visitDeclaration(declaration: IrDeclarationBase, data: IrBuilderWithScope) = + super.visitDeclaration(declaration, + data = (declaration as? IrSymbolOwner)?.let { context.createIrBuilder(it.symbol, it.startOffset, it.endOffset) } + ?: data + ) - override fun visitClassReference(expression: IrClassReference): IrExpression { - expression.transformChildrenVoid() + override fun visitClassReference(expression: IrClassReference, data: IrBuilderWithScope): IrExpression { + expression.transformChildren(this, data) - return builder.at(expression).run { + return data.at(expression).run { (expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) } ?: // E.g. for `T::class` in a body of an inline function itself. @@ -41,10 +52,10 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass { } } - override fun visitGetClass(expression: IrGetClass): IrExpression { - expression.transformChildrenVoid() + override fun visitGetClass(expression: IrGetClass, data: IrBuilderWithScope): IrExpression { + expression.transformChildren(this, data) - return builder.at(expression).run { + return data.at(expression).run { irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply { val typeInfo = irCall(symbols.getObjectTypeInfo).apply { putValueArgument(0, expression.argument) @@ -55,8 +66,8 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass { } } - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) + override fun visitCall(expression: IrCall, data: IrBuilderWithScope): IrExpression { + expression.transformChildren(this, data) // Function inlining is changing function symbol at callsite // and unbound symbol replacement is happening later. @@ -83,13 +94,16 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass { context.irBuiltIns.stringType, IrConstKind.String, builder.toString())) } else if (Symbols.isTypeOfIntrinsic(expression.symbol)) { - return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters = true)) { - builder.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false) + // Inline functions themselves are not called (they have been inlined at all call sites), + // so it is ok not to build exact type parameters for them. + val needExactTypeParameters = (container as? IrSimpleFunction)?.isInline != true + return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters)) { + data.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false) } } return expression } - }) + }, data = context.createIrBuilder((container as IrSymbolOwner).symbol, irBody.startOffset, irBody.endOffset)) } } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt index 855cf466a0c..195b0ce988b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt @@ -567,7 +567,8 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme if (type !is IrSimpleType) return val classifier = type.classifier - if (classifier is IrTypeParameterSymbol) + if (classifier is IrTypeParameterSymbol + && !classifier.owner.isReified /* Reified may be substituted with valid types later */) checkIrKTypeParameter(irElement, classifier.owner, seenTypeParameters) type.arguments.forEach { diff --git a/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt b/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt index 5dc5670251e..dcfbad22c2d 100644 --- a/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt +++ b/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt @@ -76,3 +76,13 @@ fun test_reifiedUpperBound() { assertTrue((t as KTypeParameter).isReified) assertEquals("T", (t as KTypeParameter).name) } + +@OptIn(kotlin.ExperimentalStdlibApi::class) +inline fun > recursionInReified() = typeOf>() + +@Test +fun test_recursionInReified() { + val l = recursionInReified() + assertEquals(List::class, l.classifier) + assertEquals(Int::class, l.arguments.single().type!!.classifier) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/compilerChecks/t59.kt b/kotlin-native/backend.native/tests/compilerChecks/t59.kt index 66d180a17d0..8eef6f61848 100644 --- a/kotlin-native/backend.native/tests/compilerChecks/t59.kt +++ b/kotlin-native/backend.native/tests/compilerChecks/t59.kt @@ -1,7 +1,7 @@ import kotlin.reflect.* @OptIn(kotlin.ExperimentalStdlibApi::class) -inline fun > foo() { +inline fun > foo() { typeOf>() }