[IR] Fix for https://youtrack.jetbrains.com/issue/KT-44219 + test
This commit is contained in:
committed by
Nikolay Krasko
parent
aed23ff098
commit
1222b72dcd
+32
-18
@@ -5,35 +5,46 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
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.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.at
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.renderCompilerError
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
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.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:
|
* This pass runs after inlining and performs the following additional transformations over some operations:
|
||||||
* - Convert immutableBlobOf() arguments to special IrConst.
|
* - Convert immutableBlobOf() arguments to special IrConst.
|
||||||
* - Convert `obj::class` and `Class::class` to calls.
|
* - 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
|
private val symbols get() = context.ir.symbols
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
val irFile = container.file
|
||||||
|
irBody.transformChildren(object : IrElementTransformer<IrBuilderWithScope> {
|
||||||
|
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 {
|
override fun visitClassReference(expression: IrClassReference, data: IrBuilderWithScope): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildren(this, data)
|
||||||
|
|
||||||
return builder.at(expression).run {
|
return data.at(expression).run {
|
||||||
(expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) }
|
(expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) }
|
||||||
?:
|
?:
|
||||||
// E.g. for `T::class` in a body of an inline function itself.
|
// 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 {
|
override fun visitGetClass(expression: IrGetClass, data: IrBuilderWithScope): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildren(this, data)
|
||||||
|
|
||||||
return builder.at(expression).run {
|
return data.at(expression).run {
|
||||||
irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply {
|
irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply {
|
||||||
val typeInfo = irCall(symbols.getObjectTypeInfo).apply {
|
val typeInfo = irCall(symbols.getObjectTypeInfo).apply {
|
||||||
putValueArgument(0, expression.argument)
|
putValueArgument(0, expression.argument)
|
||||||
@@ -55,8 +66,8 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall, data: IrBuilderWithScope): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildren(this, data)
|
||||||
|
|
||||||
// Function inlining is changing function symbol at callsite
|
// Function inlining is changing function symbol at callsite
|
||||||
// and unbound symbol replacement is happening later.
|
// and unbound symbol replacement is happening later.
|
||||||
@@ -83,13 +94,16 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
context.irBuiltIns.stringType,
|
context.irBuiltIns.stringType,
|
||||||
IrConstKind.String, builder.toString()))
|
IrConstKind.String, builder.toString()))
|
||||||
} else if (Symbols.isTypeOfIntrinsic(expression.symbol)) {
|
} else if (Symbols.isTypeOfIntrinsic(expression.symbol)) {
|
||||||
return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters = true)) {
|
// Inline functions themselves are not called (they have been inlined at all call sites),
|
||||||
builder.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false)
|
// 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
|
return expression
|
||||||
}
|
}
|
||||||
})
|
}, data = context.createIrBuilder((container as IrSymbolOwner).symbol, irBody.startOffset, irBody.endOffset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-1
@@ -567,7 +567,8 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
if (type !is IrSimpleType)
|
if (type !is IrSimpleType)
|
||||||
return
|
return
|
||||||
val classifier = type.classifier
|
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)
|
checkIrKTypeParameter(irElement, classifier.owner, seenTypeParameters)
|
||||||
|
|
||||||
type.arguments.forEach {
|
type.arguments.forEach {
|
||||||
|
|||||||
@@ -76,3 +76,13 @@ fun test_reifiedUpperBound() {
|
|||||||
assertTrue((t as KTypeParameter).isReified)
|
assertTrue((t as KTypeParameter).isReified)
|
||||||
assertEquals("T", (t as KTypeParameter).name)
|
assertEquals("T", (t as KTypeParameter).name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||||
|
inline fun <reified T : Comparable<T>> recursionInReified() = typeOf<List<T>>()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_recursionInReified() {
|
||||||
|
val l = recursionInReified<Int>()
|
||||||
|
assertEquals(List::class, l.classifier)
|
||||||
|
assertEquals(Int::class, l.arguments.single().type!!.classifier)
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import kotlin.reflect.*
|
import kotlin.reflect.*
|
||||||
|
|
||||||
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||||
inline fun <reified T : Comparable<T>> foo() {
|
inline fun <T : Comparable<T>> foo() {
|
||||||
typeOf<List<T>>()
|
typeOf<List<T>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user