Skip to content

Commit 6b203b9

Browse files
AbdullinAMSpace Cloud
authored andcommitted
#KT-78374 Make indy lambda function name generation more consistent
Co-authored-by: Alexander Udalov <[email protected]> Merge-request: KOTLIN-MR-1516 Merged-by: Azat Abdullin <[email protected]>
1 parent bdb3834 commit 6b203b9

File tree

37 files changed

+419
-366
lines changed

37 files changed

+419
-366
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
public final class MainKt {
22
// source: 'main.kt'
3-
private final static method ArticleScreenContent$lambda$1$lambda$0(p0: java.lang.String): kotlin.Unit
4-
private final static method ArticleScreenContent$lambda$1(p0: java.lang.String): kotlin.jvm.functions.Function0
3+
private final static method ArticleScreenContent$lambda$0$0(p0: java.lang.String): kotlin.Unit
4+
private final static method ArticleScreenContent$lambda$0(p0: java.lang.String): kotlin.jvm.functions.Function0
55
private final static method ArticleScreenContent(p0: java.lang.String): void
66
private final static method TopAppBar(p0: java.lang.String): void
77
}

compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ open class LocalDeclarationsLowering(
134134
val newParameterToOld: MutableMap<IrValueParameter, IrValueParameter> = mutableMapOf(),
135135
val oldParameterToNew: MutableMap<IrValueParameter, IrValueParameter> = mutableMapOf(),
136136
) : BodyLoweringPass {
137+
internal val methodScopesWithCounter: MutableMap<IrClass, MutableMap<Name, ScopeWithCounter>> = mutableMapOf()
137138

138139
open val invalidChars: Set<Char>
139140
get() = emptySet()
@@ -221,6 +222,12 @@ open class LocalDeclarationsLowering(
221222
private fun IrSymbolOwner.getOrCreateScopeWithCounter(): ScopeWithCounter =
222223
scopeWithCounter ?: ScopeWithCounter(this).also { scopeWithCounter = it }
223224

225+
private fun IrFunction.getOrCreateScopeWithCounter(): ScopeWithCounter? {
226+
val klass = parentClassOrNull ?: return null
227+
return methodScopesWithCounter.getOrPut(klass, ::mutableMapOf)
228+
.getOrPut(this.name) { ScopeWithCounter(this) }
229+
}
230+
224231
abstract class LocalContext {
225232
val capturedTypeParameterToTypeParameter: MutableMap<IrTypeParameter, IrTypeParameter> = mutableMapOf()
226233

@@ -284,6 +291,7 @@ open class LocalDeclarationsLowering(
284291
val index: Int,
285292
val ownerForLoweredDeclaration: OwnerForLoweredDeclaration,
286293
sourceFileWhenInlined: IrFileEntry?,
294+
val isNestedInLambda: Boolean,
287295
) :
288296
LocalContextWithClosureAsParameters(sourceFileWhenInlined) {
289297
lateinit var closure: Closure
@@ -896,15 +904,20 @@ open class LocalDeclarationsLowering(
896904
private fun suggestLocalName(declaration: IrDeclarationWithName): String {
897905
val declarationName = localNameSanitizer(declaration.name.asString())
898906
localFunctions[declaration]?.let {
899-
val baseName = if (declaration.name.isSpecial) "lambda" else declarationName
907+
val baseName = when {
908+
declaration.name.isSpecial -> if (it.isNestedInLambda) "" else "lambda"
909+
else -> declarationName
910+
}
900911
if (it.index >= 0) {
901912
if (!suggestUniqueNames) return baseName
902913

903-
val separator = if (
914+
val separator = when {
904915
compatibilityModeForInlinedLocalDelegatedPropertyAccessors &&
905-
declaration.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR &&
906-
container is IrFunction && container.isInline
907-
) "-" else "$"
916+
declaration.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR &&
917+
container is IrFunction && container.isInline -> "-"
918+
baseName.isEmpty() -> ""
919+
else -> "$"
920+
}
908921
return "$baseName$separator${it.index}"
909922
}
910923
}
@@ -1213,37 +1226,57 @@ open class LocalDeclarationsLowering(
12131226
}
12141227
}
12151228

1229+
private val IrFunction.isLambda: Boolean
1230+
get() =
1231+
origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA || origin == IrDeclarationOrigin.INLINE_LAMBDA
1232+
1233+
private inline fun <reified T : IrElement> getEnclosing(): T? {
1234+
var currentParent = container as? T ?: container.parent
1235+
while (currentParent is IrDeclaration && currentParent !is T) {
1236+
currentParent = currentParent.parent
1237+
}
1238+
1239+
return currentParent as? T
1240+
}
1241+
12161242
private fun collectLocalDeclarations() {
12171243
val enclosingPackageFragment = container.getPackageFragment()
1218-
val enclosingClass = run {
1219-
var currentParent = container as? IrClass ?: container.parent
1220-
while (currentParent is IrDeclaration && currentParent !is IrClass) {
1221-
currentParent = currentParent.parent
1222-
}
1223-
1224-
currentParent as? IrClass
1244+
val enclosingClass = getEnclosing<IrClass>()
1245+
val enclosingFunction = getEnclosing<IrFunction>().takeIf {
1246+
it !is IrConstructor && it?.parentClassOrNull != null
12251247
}
12261248

12271249
class Data(
1228-
val currentClass: ScopeWithCounter?,
1250+
val currentScope: ScopeWithCounter?,
12291251
val isInInlineFunction: Boolean,
12301252
val sourceFileWhenInlined: IrFileEntry? = null,
1253+
val isInLambdaFunction: Boolean,
12311254
) {
12321255
fun withCurrentClass(currentClass: IrClass): Data =
12331256
// Don't cache local declarations
1234-
Data(ScopeWithCounter(currentClass), isInInlineFunction, sourceFileWhenInlined)
1257+
Data(ScopeWithCounter(currentClass), isInInlineFunction, sourceFileWhenInlined, false)
1258+
1259+
fun withCurrentFunction(currentFunction: IrFunction): Data =
1260+
Data(ScopeWithCounter(currentFunction), isInInlineFunction, sourceFileWhenInlined, currentFunction.isLambda)
12351261

12361262
fun withInline(isInline: Boolean, sourceFileWhenInlined: IrFileEntry?): Data =
1237-
if (isInline && !isInInlineFunction) Data(currentClass, true, sourceFileWhenInlined) else this
1263+
if (isInline && !isInInlineFunction) Data(currentScope, true, sourceFileWhenInlined, false) else this
12381264
}
12391265

12401266
irElement.accept(object : IrVisitor<Unit, Data>() {
1267+
12411268
override fun visitElement(element: IrElement, data: Data) {
12421269
element.acceptChildren(this, data)
12431270
}
12441271

12451272
override fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: Data) {
1246-
super.visitInlinedFunctionBlock(inlinedBlock, data.withInline(inlinedBlock.isFunctionInlining(),inlinedBlock.inlinedFunctionFileEntry))
1273+
super.visitInlinedFunctionBlock(
1274+
inlinedBlock,
1275+
data.withInline(
1276+
inlinedBlock.isFunctionInlining(),
1277+
inlinedBlock.inlinedFunctionFileEntry
1278+
)
1279+
)
12471280
}
12481281

12491282
override fun visitFunctionExpression(expression: IrFunctionExpression, data: Data) {
@@ -1268,10 +1301,10 @@ open class LocalDeclarationsLowering(
12681301

12691302
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Data) {
12701303
if (functionsToSkip?.contains(declaration) == true) return
1271-
super.visitSimpleFunction(declaration, data.withInline(declaration.isInline, data.sourceFileWhenInlined))
12721304

12731305
if (declaration.visibility == DescriptorVisibilities.LOCAL) {
1274-
val enclosingScope = data.currentClass
1306+
val enclosingScope = data.currentScope
1307+
?: enclosingFunction?.getOrCreateScopeWithCounter()
12751308
?: enclosingClass?.getOrCreateScopeWithCounter()
12761309
// File is required for K/N because file declarations are not split by classes.
12771310
?: enclosingPackageFragment.getOrCreateScopeWithCounter()
@@ -1280,14 +1313,34 @@ open class LocalDeclarationsLowering(
12801313
enclosingScope.counter++
12811314
else -1
12821315
val ownerForLoweredDeclaration =
1283-
data.currentClass?.let { OwnerForLoweredDeclaration.DeclarationContainer(it.irElement as IrDeclarationContainer) }
1316+
data.currentScope?.let {
1317+
when (it.irElement) {
1318+
is IrDeclarationContainer -> OwnerForLoweredDeclaration.DeclarationContainer(it.irElement)
1319+
is IrFunction -> localFunctions[enclosingScope.irElement]!!.ownerForLoweredDeclaration
1320+
else -> error("Unknown owner for lowered declaration")
1321+
}
1322+
}
12841323
?: (irElement as? IrBlock)?.let { OwnerForLoweredDeclaration.Block(irElement, closestParent!!) }
1324+
?: (enclosingScope.irElement as? IrFunction)?.let { enclosingFunction ->
1325+
OwnerForLoweredDeclaration.DeclarationContainer(enclosingFunction.parentClassOrNull!!)
1326+
}
12851327
?: OwnerForLoweredDeclaration.DeclarationContainer(enclosingScope.irElement as IrDeclarationContainer)
1286-
localFunctions[declaration] =
1287-
LocalFunctionContext(declaration, index, ownerForLoweredDeclaration, data.sourceFileWhenInlined)
1328+
localFunctions[declaration] = LocalFunctionContext(
1329+
declaration,
1330+
index,
1331+
ownerForLoweredDeclaration,
1332+
data.sourceFileWhenInlined,
1333+
data.isInLambdaFunction,
1334+
)
12881335

12891336
enclosingScope.usedLocalFunctionNames.add(declaration.name)
12901337
}
1338+
1339+
val newData = data.withInline(declaration.isInline, data.sourceFileWhenInlined)
1340+
super.visitSimpleFunction(
1341+
declaration,
1342+
if (declaration.isLambda) newData.withCurrentFunction(declaration) else newData
1343+
)
12911344
}
12921345

12931346
override fun visitConstructor(declaration: IrConstructor, data: Data) {
@@ -1323,7 +1376,7 @@ open class LocalDeclarationsLowering(
13231376
private val Data.inInlineFunctionScope: Boolean
13241377
get() = isInInlineFunction ||
13251378
generateSequence(container) { it.parent as? IrDeclaration }.any { it is IrFunction && it.isInline }
1326-
}, Data(null, false, null))
1379+
}, Data(null, false, null, false))
13271380
}
13281381
}
13291382
}

compiler/testData/codegen/asmLike/receiverMangling/deepInline.asm.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ public final class DeepInlineKt : java/lang/Object {
88
public final static void foo(java.lang.String $this$foo, int count) {
99
Local variables:
1010
16 $i$a$-block-DeepInlineKt$foo$1$1$1: I
11-
14 $this$foo_u24lambda_u242_u24lambda_u241_u24lambda_u240: J
11+
14 $this$foo_u24lambda_u240_u240_u240: J
1212
13 $i$f$block: I
1313
11 $i$a$-block-DeepInlineKt$foo$1$1: I
1414
12 z: Z
15-
9 $this$foo_u24lambda_u242_u24lambda_u241: J
15+
9 $this$foo_u24lambda_u240_u240: J
1616
8 $i$f$block: I
1717
6 $i$a$-block-DeepInlineKt$foo$1: I
1818
7 y: Z
19-
4 $this$foo_u24lambda_u242: J
19+
4 $this$foo_u24lambda_u240: J
2020
3 $i$f$block: I
2121
2 x: Z
2222
0 $this$foo: Ljava/lang/String;

compiler/testData/codegen/asmLike/receiverMangling/deepInlineWithLabels.asm.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ public final class DeepInlineWithLabelsKt : java/lang/Object {
88
public final static void foo(java.lang.String $this$foo, int count) {
99
Local variables:
1010
16 $i$a$-block-DeepInlineWithLabelsKt$foo$1$1$1: I
11-
14 $this$foo_u24lambda_u242_u24lambda_u241_u24lambda_u240: J
11+
14 $this$foo_u24lambda_u240_u240_u240: J
1212
13 $i$f$block: I
1313
11 $i$a$-block-DeepInlineWithLabelsKt$foo$1$1: I
1414
12 z: Z
15-
9 $this$foo_u24lambda_u242_u24lambda_u241: J
15+
9 $this$foo_u24lambda_u240_u240: J
1616
8 $i$f$block: I
1717
6 $i$a$-block-DeepInlineWithLabelsKt$foo$1: I
1818
7 y: Z
19-
4 $this$foo_u24lambda_u242: J
19+
4 $this$foo_u24lambda_u240: J
2020
3 $i$f$block: I
2121
2 x: Z
2222
0 $this$foo: Ljava/lang/String;

compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.ir.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,25 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
135135
}
136136

137137
@kotlin.Metadata
138-
public final class CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1$1 {
139-
enclosing method CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1.send(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
138+
public final class CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1$1 {
139+
enclosing method CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1.send(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
140140
field label: int
141141
synthetic field result: java.lang.Object
142-
synthetic final field this$0: CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1
143-
inner (anonymous) class CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1
144-
inner (anonymous) class CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1$1
145-
public method <init>(p0: CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1, p1: kotlin.coroutines.Continuation): void
142+
synthetic final field this$0: CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1
143+
inner (anonymous) class CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1
144+
inner (anonymous) class CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1$1
145+
public method <init>(p0: CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1, p1: kotlin.coroutines.Continuation): void
146146
public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
147147
}
148148

149149
@kotlin.Metadata
150-
public final class CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1 {
150+
public final class CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1 {
151151
// source: 'crossinline.kt'
152152
enclosing method CrossinlineKt.filter(LSourceCrossinline;Lkotlin/jvm/functions/Function1;)LSourceCrossinline;
153153
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
154154
synthetic final field $this_source$inlined: Sink
155-
inner (anonymous) class CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1
156-
inner (anonymous) class CrossinlineKt$filter$lambda$3$$inlined$consumeEach$1$1
155+
inner (anonymous) class CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1
156+
inner (anonymous) class CrossinlineKt$filter$lambda$0$$inlined$consumeEach$1$1
157157
public method <init>(p0: kotlin.jvm.functions.Function1, p1: Sink): void
158158
public method close(p0: java.lang.Throwable): void
159159
public method send$$forInline(p0: java.lang.Object, p1: kotlin.coroutines.Continuation): java.lang.Object

compiler/testData/codegen/box/delegatedProperty/delegateToFinalProperty/memberExtensionPropertyAndLocalDelegatedProperty.ir.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public final class MemberExtensionPropertyAndLocalDelegatedPropertyKt {
2424
// source: 'memberExtensionPropertyAndLocalDelegatedProperty.kt'
2525
synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[]
2626
static method <clinit>(): void
27-
private final static method box$lambda$1$lambda$0(p0: Delegate): java.lang.String
27+
private final static method box$lambda$0$0(p0: Delegate): java.lang.String
2828
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
2929
}
3030

0 commit comments

Comments
 (0)