JVM_IR: propagate reified type parameter usages from inline lambdas

...to whichever class they are inlined into, not the class they are
declared in (which is not the same if the lambda is crossinline).

 #KT-46584 Fixed
This commit is contained in:
pyos
2021-05-11 16:19:20 +02:00
committed by TeamCityServer
parent e079fb665e
commit 3fc2cc410c
19 changed files with 175 additions and 45 deletions
@@ -58,6 +58,8 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
lateinit var node: SMAPAndMethodNode lateinit var node: SMAPAndMethodNode
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>)
open val hasDispatchReceiver = true open val hasDispatchReceiver = true
@@ -198,7 +200,7 @@ abstract class DefaultLambda(
if (needReification) { if (needReification) {
//nested classes could also require reification //nested classes could also require reification
reifiedTypeInliner.reifyInstructions(node.node) reifiedTypeParametersUsages.mergeAll(reifiedTypeInliner.reifyInstructions(node.node))
} }
} }
@@ -225,7 +227,7 @@ internal fun Type.boxReceiverForBoundReference(kotlinType: KotlinType, typeMappe
abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInline) { abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInline) {
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) { override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
node = sourceCompiler.generateLambdaBody(this) node = sourceCompiler.generateLambdaBody(this, reifiedTypeParametersUsages)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false) node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
} }
@@ -264,7 +264,7 @@ class MethodInliner(
visitInsn(Opcodes.NOP) visitInsn(Opcodes.NOP)
} }
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info, sourceMapper.parent) inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info.node.node, sourceMapper.parent)
addInlineMarker(this, true) addInlineMarker(this, true)
val lambdaParameters = info.addAllParameters(nodeRemapper) val lambdaParameters = info.addAllParameters(nodeRemapper)
@@ -289,6 +289,7 @@ class MethodInliner(
val lambdaResult = inliner.doInline(localVariablesSorter, varRemapper, true, info.returnLabels, invokeCall.finallyDepthShift) val lambdaResult = inliner.doInline(localVariablesSorter, varRemapper, true, info.returnLabels, invokeCall.finallyDepthShift)
result.mergeWithNotChangeInfo(lambdaResult) result.mergeWithNotChangeInfo(lambdaResult)
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages) result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
result.reifiedTypeParametersUsages.mergeAll(info.reifiedTypeParametersUsages)
StackValue StackValue
.onStack(info.invokeMethod.returnType, info.invokeMethodReturnType) .onStack(info.invokeMethod.returnType, info.invokeMethodReturnType)
@@ -48,7 +48,7 @@ interface SourceCompilerForInline {
val lazySourceMapper: SourceMapper val lazySourceMapper: SourceMapper
fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode
fun doCreateMethodNodeFromSource( fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor, callableDescriptor: FunctionDescriptor,
@@ -130,7 +130,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
override val lazySourceMapper override val lazySourceMapper
get() = codegen.parentCodegen.orCreateSourceMapper get() = codegen.parentCodegen.orCreateSourceMapper
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode { override fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode {
lambdaInfo as? PsiExpressionLambda ?: error("TODO") lambdaInfo as? PsiExpressionLambda ?: error("TODO")
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
val jvmMethodSignature = state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor) val jvmMethodSignature = state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
@@ -579,8 +579,8 @@ class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
const val LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER = 1 const val LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER = 1
} }
fun onInlineLambdaStart(mv: MethodVisitor, info: LambdaInfo, smap: SourceMapper) { fun onInlineLambdaStart(mv: MethodVisitor, lambda: MethodNode, smap: SourceMapper) {
val firstLine = info.node.node.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1 val firstLine = lambda.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
if (callLineNumber >= 0 && firstLine == callLineNumber) { if (callLineNumber >= 0 && firstLine == callLineNumber) {
// We want the debugger to be able to break both on the inline call itself, plus on each // We want the debugger to be able to break both on the inline call itself, plus on each
// invocation of the inline lambda passed to it. For that to happen there needs to be at least // invocation of the inline lambda passed to it. For that to happen there needs to be at least
@@ -3714,6 +3714,18 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -143,6 +143,7 @@ class ExpressionCodegen(
val classCodegen: ClassCodegen, val classCodegen: ClassCodegen,
val inlinedInto: ExpressionCodegen?, val inlinedInto: ExpressionCodegen?,
val smap: SourceMapper, val smap: SourceMapper,
val reifiedTypeParametersUsages: ReifiedTypeParametersUsages,
) : IrElementVisitor<PromisedValue, BlockInfo>, BaseExpressionCodegen { ) : IrElementVisitor<PromisedValue, BlockInfo>, BaseExpressionCodegen {
var finallyDepth = 0 var finallyDepth = 0
@@ -1426,32 +1427,13 @@ class ExpressionCodegen(
override fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker) { override fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker) {
require(typeParameter is IrTypeParameterSymbol) require(typeParameter is IrTypeParameterSymbol)
// This is a hack to work around the problem in LocalDeclarationsLowering. Specifically, suppose an inline if (irFunction != typeParameter.owner.parent) {
// lambda uses a reified type parameter declared by a function: reifiedTypeParametersUsages.addUsedReifiedParameter(typeParameter.owner.name.asString())
//
// object {
// inline fun <reified T : Any> f() = run { T::class.java.getName() }
// }
//
// LocalDeclarationsLowering would extract that lambda into a method of the enclosing type, but will not create
// a reified type parameter in it (in fact, the lambda method isn't even marked as inline):
//
// object {
// /* static */ private fun `f$lambda-0`() = T::class.java.getName()
// inline fun <reified T : Any> f() = run(::`f$lambda-0`)
// }
//
// The parent of the type parameter then is not `irFunction` (i.e. the lambda itself), but the function
// it is inlined into.
//
// TODO make LocalDeclarationsLowering handle captured type parameters and only compare with `irFunction`.
if (generateSequence(this) { it.inlinedInto }.none { it.irFunction == typeParameter.owner.parent }) {
classCodegen.reifiedTypeParametersUsages.addUsedReifiedParameter(typeParameter.owner.name.asString())
} }
} }
override fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages) { override fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages) {
classCodegen.reifiedTypeParametersUsages.propagateChildUsagesWithinContext(reifiedTypeParametersUsages) { this.reifiedTypeParametersUsages.propagateChildUsagesWithinContext(reifiedTypeParametersUsages) {
irFunction.typeParameters.filter { it.isReified }.map { it.name.asString() }.toSet() irFunction.typeParameters.filter { it.isReified }.map { it.name.asString() }.toSet()
} }
} }
@@ -13,10 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.inline.MethodBodyVisitor import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.inline.SMAP
import org.jetbrains.kotlin.codegen.inline.SMAPAndMethodNode
import org.jetbrains.kotlin.codegen.inline.wrapWithMaxLocalCalc
import org.jetbrains.kotlin.codegen.mangleNameIfNeeded import org.jetbrains.kotlin.codegen.mangleNameIfNeeded
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount
@@ -40,21 +37,20 @@ import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
class FunctionCodegen( class FunctionCodegen(private val irFunction: IrFunction, private val classCodegen: ClassCodegen) {
private val irFunction: IrFunction,
private val classCodegen: ClassCodegen,
private val inlinedInto: ExpressionCodegen? = null
) {
private val context = classCodegen.context private val context = classCodegen.context
fun generate(): SMAPAndMethodNode = fun generate(
inlinedInto: ExpressionCodegen? = null,
reifiedTypeParameters: ReifiedTypeParametersUsages = classCodegen.reifiedTypeParametersUsages
): SMAPAndMethodNode =
try { try {
doGenerate() doGenerate(inlinedInto, reifiedTypeParameters)
} catch (e: Throwable) { } catch (e: Throwable) {
throw RuntimeException("Exception while generating code for:\n${irFunction.dump()}", e) throw RuntimeException("Exception while generating code for:\n${irFunction.dump()}", e)
} }
private fun doGenerate(): SMAPAndMethodNode { private fun doGenerate(inlinedInto: ExpressionCodegen?, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode {
val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction) val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction)
val flags = irFunction.calculateMethodFlags() val flags = irFunction.calculateMethodFlags()
val isSynthetic = flags.and(Opcodes.ACC_SYNTHETIC) != 0 val isSynthetic = flags.and(Opcodes.ACC_SYNTHETIC) != 0
@@ -121,7 +117,9 @@ class FunctionCodegen(
context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().toIrBasedDescriptor()) context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().toIrBasedDescriptor())
try { try {
val adapter = InstructionAdapter(methodVisitor) val adapter = InstructionAdapter(methodVisitor)
ExpressionCodegen(irFunction, signature, frameMap, adapter, classCodegen, inlinedInto, sourceMapper).generate() ExpressionCodegen(
irFunction, signature, frameMap, adapter, classCodegen, inlinedInto, sourceMapper, reifiedTypeParameters
).generate()
} finally { } finally {
context.state.globalInlineContext.exitDeclaration() context.state.globalInlineContext.exitDeclaration()
} }
@@ -95,8 +95,15 @@ class IrSourceCompilerForInline(
override val lazySourceMapper: SourceMapper override val lazySourceMapper: SourceMapper
get() = codegen.smap get() = codegen.smap
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode = override fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode {
FunctionCodegen((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, codegen).generate() require(lambdaInfo is IrExpressionLambdaImpl)
for (typeParameter in lambdaInfo.function.typeParameters) {
if (typeParameter.isReified) {
reifiedTypeParameters.addUsedReifiedParameter(typeParameter.name.asString())
}
}
return FunctionCodegen(lambdaInfo.function, codegen.classCodegen).generate(codegen, reifiedTypeParameters)
}
override fun doCreateMethodNodeFromSource( override fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor, callableDescriptor: FunctionDescriptor,
@@ -116,7 +123,7 @@ class IrSourceCompilerForInline(
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) = override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
ExpressionCodegen( ExpressionCodegen(
codegen.irFunction, codegen.signature, codegen.frameMap, InstructionAdapter(finallyNode), codegen.classCodegen, codegen.irFunction, codegen.signature, codegen.frameMap, InstructionAdapter(finallyNode), codegen.classCodegen,
codegen.inlinedInto, codegen.smap codegen.inlinedInto, codegen.smap, codegen.reifiedTypeParametersUsages
).also { ).also {
it.finallyDepth = curFinallyDepth it.finallyDepth = curFinallyDepth
} }
+13
View File
@@ -0,0 +1,13 @@
// FILE: 1.kt
package test
inline fun foo(crossinline x: () -> String) = { x() }()
inline fun <reified T> bar() = foo { { T::class.simpleName!! }() }
// FILE: 2.kt
import test.*
class OK
fun box() = bar<OK>()
@@ -0,0 +1,13 @@
// FILE: 1.kt
package test
inline fun foo(x: () -> String) = x()
inline fun <reified T> bar() = { foo { { T::class.simpleName!! }() } }()
// FILE: 2.kt
import test.*
class OK
fun box() = bar<OK>()
@@ -3714,6 +3714,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -3714,6 +3714,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -3714,6 +3714,18 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -3714,6 +3714,18 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -3714,6 +3714,18 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -3714,6 +3714,18 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst
runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt44770_2.kt");
} }
@Test
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@Test
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@Test @Test
@TestMetadata("kt6988.kt") @TestMetadata("kt6988.kt")
public void testKt6988() throws Exception { public void testKt6988() throws Exception {
@@ -3025,6 +3025,16 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline
runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt");
} }
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@TestMetadata("kt7017.kt") @TestMetadata("kt7017.kt")
public void testKt7017() throws Exception { public void testKt7017() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt7017.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt7017.kt");
@@ -3025,6 +3025,16 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt");
} }
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@TestMetadata("kt7017.kt") @TestMetadata("kt7017.kt")
public void testKt7017() throws Exception { public void testKt7017() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt7017.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt7017.kt");
@@ -3025,6 +3025,16 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt35511_try_values.kt");
} }
@TestMetadata("kt46584.kt")
public void testKt46584() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584.kt");
}
@TestMetadata("kt46584_2.kt")
public void testKt46584_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt46584_2.kt");
}
@TestMetadata("kt7017.kt") @TestMetadata("kt7017.kt")
public void testKt7017() throws Exception { public void testKt7017() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/kt7017.kt"); runTest("compiler/testData/codegen/boxInline/reified/kt7017.kt");