diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index fda7910d093..3f1706e47ff 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements import org.jetbrains.kotlin.codegen.ClassBuilder +import org.jetbrains.kotlin.codegen.inline.NameGenerator import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -35,6 +36,7 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.resolve.jvm.JvmClassName @@ -71,6 +73,13 @@ class JvmBackendContext( localClassInfo[container.attributeOwnerId] = value } + // TODO cache these at ClassCodegen level. Currently, sharing this map between classes in a module is required + // because IrSourceCompilerForInline constructs a new (Fake)ClassCodegen for every call to + // an inline function in the same module. Thus, if two inline functions happen to have the same name + // and call a third inline function that has an anonymous object, the one which is called last + // will overwrite the other's regenerated copy. (Or don't recompile the inline function for every call.) + internal val regeneratedObjectNameGenerators = mutableMapOf, NameGenerator>() + internal val localDelegatedProperties = mutableMapOf>() internal val multifileFacadesToAdd = mutableMapOf>() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index cda623491ac..53665297b12 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.constantValue import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper +import org.jetbrains.kotlin.codegen.inline.NameGenerator import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages import org.jetbrains.kotlin.codegen.inline.SourceMapper import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings @@ -26,6 +27,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME @@ -82,6 +84,13 @@ open class ClassCodegen protected constructor( else -> null } + fun getRegeneratedObjectNameGenerator(function: IrFunction): NameGenerator { + val name = if (function.name.isSpecial) Name.identifier("special") else function.name + return context.regeneratedObjectNameGenerators.getOrPut(irClass to name) { + NameGenerator("${type.internalName}\$$name\$\$inlined") + } + } + fun generate(): ReifiedTypeParametersUsages { if (withinInline) { getOrCreateSourceMapper() //initialize default mapping that would be later written in class file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index e87a6679828..c9100684e58 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -116,7 +116,7 @@ class ExpressionCodegen( override val visitor: InstructionAdapter get() = mv - override val inlineNameGenerator: NameGenerator = NameGenerator("${classCodegen.type.internalName}\$todo") // TODO + override val inlineNameGenerator: NameGenerator = classCodegen.getRegeneratedObjectNameGenerator(irFunction) override val typeSystem: TypeSystemCommonBackendContext get() = typeMapper.typeSystem diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index e07aa6e0bff..a9e4e3cab74 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -151,11 +151,14 @@ class IrExpressionLambdaImpl( return false //always false } - companion object { - private var counter: Int = 123//TODO: pass proper type - } - - override val lambdaClassType: Type = Type.getObjectType("test${counter++}") + // This name doesn't actually matter: it is used internally to tell this lambda's captured + // arguments apart from any other scope's. So long as it's unique, any value is fine. + // This particular string slightly aids in debugging internal compiler errors as it at least + // points towards the function containing the lambda. + override val lambdaClassType: Type = Type.getObjectType( + context.getLocalClassInfo(reference)?.internalName + ?: throw AssertionError("callable reference ${reference.dump()} has no name in context") + ) override val capturedVars: List = arrayListOf().apply { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableRefereceToLambda.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt similarity index 97% rename from compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableRefereceToLambda.kt rename to compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt index a17fe244252..2c3ddc59581 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableRefereceToLambda.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InlineCallableReferenceToLambda.kt @@ -24,10 +24,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildFun -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.util.defaultType @@ -51,6 +48,7 @@ internal val inlineCallableReferenceToLambdaPhase = makeIrFilePhase( // internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendContext) : FileLoweringPass { private val inlinableCR = mutableSetOf() + override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { @@ -118,7 +116,9 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte expression.startOffset, expression.endOffset, field.type, newLambda.symbol, newLambda.symbol.descriptor, 0, IrStatementOrigin.LAMBDA - ) + ).apply { + copyAttributes(expression) + } } } @@ -209,7 +209,9 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte expression.startOffset, expression.endOffset, referencedFunction.returnType, newLambda.symbol, newLambda.symbol.descriptor, referencedFunction.typeParameters.size, IrStatementOrigin.LAMBDA - ) + ).apply { + copyAttributes(expression) + } } } } \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt b/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt index 5a0b800ab50..80e630ccc3b 100644 --- a/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt +++ b/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt b/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt new file mode 100644 index 00000000000..8c011de82e3 --- /dev/null +++ b/compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt @@ -0,0 +1,19 @@ +// FILE: 1.kt +package test + +inline fun call(crossinline f: () -> R) : R { + return { f() }() +} + +// FILE: 2.kt +//NO_CHECK_LAMBDA_INLINING +import test.* + +inline fun sameName(s: Long): String = call { "FAIL" } +inline fun sameName(s: Int): String = call { "OK" } + +fun box(): String { + val result = sameName(1) + sameName(1L) + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt b/compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt index ae452746e05..3cdd3687bf2 100644 --- a/compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt +++ b/compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index dbf5664efca..9e4fddaf99b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -1888,6 +1888,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt"); } + @TestMetadata("regeneratedLambdaName2.kt") + public void testRegeneratedLambdaName2() throws Exception { + runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt"); + } + @TestMetadata("sameCaptured.kt") public void testSameCaptured() throws Exception { runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 997413d51fb..ac8ba7c6560 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1888,6 +1888,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt"); } + @TestMetadata("regeneratedLambdaName2.kt") + public void testRegeneratedLambdaName2() throws Exception { + runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt"); + } + @TestMetadata("sameCaptured.kt") public void testSameCaptured() throws Exception { runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java index 98712a626fd..b56c3ea364a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java @@ -1888,6 +1888,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt"); } + @TestMetadata("regeneratedLambdaName2.kt") + public void testRegeneratedLambdaName2() throws Exception { + runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt"); + } + @TestMetadata("sameCaptured.kt") public void testSameCaptured() throws Exception { runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 394e3e6df72..95295dd2b22 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1888,6 +1888,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt"); } + @TestMetadata("regeneratedLambdaName2.kt") + public void testRegeneratedLambdaName2() throws Exception { + runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt"); + } + @TestMetadata("sameCaptured.kt") public void testSameCaptured() throws Exception { runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt");