Skip to content

Commit bdb3834

Browse files
zhelenskiySpace Team
authored andcommitted
[IR] Generate field names from context parameters correctly
#KT-77713
1 parent 9f4e7f5 commit bdb3834

File tree

30 files changed

+200
-14
lines changed

30 files changed

+200
-14
lines changed

analysis/low-level-api-fir/tests-gen/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLBlackBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

analysis/low-level-api-fir/tests-gen/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLReversedBlackBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ open class LocalDeclarationsLowering(
135135
val oldParameterToNew: MutableMap<IrValueParameter, IrValueParameter> = mutableMapOf(),
136136
) : BodyLoweringPass {
137137

138+
open val invalidChars: Set<Char>
139+
get() = emptySet()
140+
138141
override fun lower(irFile: IrFile) {
139142
runOnFilePostfix(irFile)
140143
}
@@ -1151,7 +1154,10 @@ open class LocalDeclarationsLowering(
11511154
}
11521155
}
11531156

1154-
val base = if (declaration.name.isSpecial) {
1157+
val baseAsContextParameter = (declaration as? IrValueParameter)?.let {
1158+
(declaration.parent as IrFunction).anonymousContextParameterName(declaration, invalidChars)
1159+
}
1160+
val base = baseAsContextParameter ?: if (declaration.name.isSpecial) {
11551161
declaration.name.asStringStripSpecialMarkers()
11561162
} else {
11571163
declaration.name.asString()

compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLocalDeclarationsLowering.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.lower.*
99
import org.jetbrains.kotlin.backend.common.phaser.PhaseDescription
1010
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
1111
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
12+
import org.jetbrains.kotlin.backend.jvm.ir.anonymousContextParameterName
1213
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
1314
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
1415
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.ir.util.parentAsClass
2425
import org.jetbrains.kotlin.ir.util.parentDeclarationsWithSelf
2526
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
2627
import org.jetbrains.kotlin.name.NameUtils
28+
import org.jetbrains.kotlin.resolve.jvm.JvmConstants
2729
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
2830

2931
/**
@@ -47,6 +49,9 @@ internal class JvmLocalDeclarationsLowering(override val context: JvmBackendCont
4749
newParameterToOld = context.evaluatorData?.localDeclarationsData?.newParameterToOld ?: mutableMapOf(),
4850
oldParameterToNew = context.evaluatorData?.localDeclarationsData?.oldParameterToNew ?: mutableMapOf(),
4951
) {
52+
override val invalidChars: Set<Char>
53+
get() = JvmConstants.INVALID_CHARS
54+
5055
override fun getReplacementSymbolForCaptured(container: IrDeclaration, symbol: IrValueSymbol): IrValueSymbol {
5156
if (context.evaluatorData?.evaluatorGeneratedFunction == container && !symbol.owner.parentDeclarationsWithSelf.contains(container)) {
5257
val newParameter = (container as IrFunction).addValueParameter {

compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -503,19 +503,7 @@ fun IrFunction.extensionReceiverName(config: JvmBackendConfig): String {
503503
AsmUtil.LABELED_THIS_PARAMETER + mangleNameIfNeeded(callableName.asString())
504504
}
505505

506-
private fun String.replaceInvalidChars() =
507-
JvmConstants.INVALID_CHARS.fold(this) { acc, ch -> if (ch in acc) acc.replace(ch, '_') else acc }
508-
509-
fun IrFunction.anonymousContextParameterName(parameter: IrValueParameter): String? {
510-
if (parameter.kind != IrParameterKind.Context || parameter.origin != UNDERSCORE_PARAMETER) return null
511-
val contextParameterNames = parameters
512-
.filter { it.kind == IrParameterKind.Context && it.origin == UNDERSCORE_PARAMETER }
513-
.associateWith { it.type.erasedUpperBound.name.asString().replaceInvalidChars() }
514-
val nameGroups = contextParameterNames.entries.groupBy({ it.value }, { it.key })
515-
val baseName = contextParameterNames[parameter]
516-
val currentNameGroup = nameGroups[baseName]!!
517-
return if (currentNameGroup.size == 1) "\$context-$baseName" else "\$context-$baseName#${currentNameGroup.indexOf(parameter) + 1}"
518-
}
506+
fun IrFunction.anonymousContextParameterName(parameter: IrValueParameter): String? = anonymousContextParameterName(parameter, JvmConstants.INVALID_CHARS)
519507

520508
fun IrFunction.isBridge(): Boolean =
521509
origin == IrDeclarationOrigin.BRIDGE || origin == IrDeclarationOrigin.BRIDGE_SPECIAL

compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
1919
import org.jetbrains.kotlin.ir.builders.declarations.*
2020
import org.jetbrains.kotlin.ir.builders.irImplicitCast
2121
import org.jetbrains.kotlin.ir.declarations.*
22+
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.Companion.UNDERSCORE_PARAMETER
2223
import org.jetbrains.kotlin.ir.expressions.*
2324
import org.jetbrains.kotlin.ir.expressions.impl.*
2425
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
3536
import org.jetbrains.kotlin.utils.*
3637
import org.jetbrains.kotlin.utils.addToStdlib.assignFrom
3738
import java.io.StringWriter
39+
import kotlin.collections.get
3840

3941
/**
4042
* Binds all arguments represented in the IR to the parameters of the accessed function.
@@ -1592,3 +1594,18 @@ val IrSimpleFunction.isTrivialGetter: Boolean
15921594

15931595
return (receiver as? IrGetValue)?.symbol?.owner === this.dispatchReceiverParameter
15941596
}
1597+
1598+
1599+
private fun String.replaceInvalidChars(invalidChars: Set<Char>) =
1600+
invalidChars.fold(this) { acc, ch -> if (ch in acc) acc.replace(ch, '_') else acc }
1601+
1602+
fun IrFunction.anonymousContextParameterName(parameter: IrValueParameter, invalidChars: Set<Char>): String? {
1603+
if (parameter.kind != IrParameterKind.Context || parameter.origin != UNDERSCORE_PARAMETER) return null
1604+
val contextParameterNames = parameters
1605+
.filter { it.kind == IrParameterKind.Context && it.origin == UNDERSCORE_PARAMETER }
1606+
.associateWith { it.type.erasedUpperBound.name.asString().replaceInvalidChars(invalidChars) }
1607+
val nameGroups = contextParameterNames.entries.groupBy({ it.value }, { it.key })
1608+
val baseName = contextParameterNames[parameter]
1609+
val currentNameGroup = nameGroups[baseName]!!
1610+
return if (currentNameGroup.size == 1) "\$context-$baseName" else "\$context-$baseName#${currentNameGroup.indexOf(parameter) + 1}"
1611+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// ISSUE: KT-77713
2+
// WITH_STDLIB
3+
// IGNORE_BACKEND_K1: ANY
4+
// LANGUAGE: +ContextParameters
5+
// CHECK_BYTECODE_TEXT
6+
7+
context(s: String)
8+
fun foo() = s
9+
10+
fun bar(f: () -> String) = f()
11+
12+
inline fun baz(crossinline f: () -> String) = bar { f() }
13+
14+
context(_: String)
15+
fun qux() = baz { foo() }
16+
17+
fun box() = context("OK") { qux() }
18+
19+
20+
// 0 unused var\$inlined

compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/JvmAbiConsistencyTestBoxGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)