mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[JVM IR] Mangle variable names for anonymous parameters in lambdas.
This commit is contained in:
committed by
Ilmir Usmanov
parent
88cac53d88
commit
31ba2d64db
@@ -237,6 +237,7 @@ private val tailrecPhase = makeIrFilePhase<JvmBackendContext>(
|
||||
|
||||
@Suppress("Reformat")
|
||||
private val jvmFilePhases =
|
||||
renameAnonymousParametersLowering then
|
||||
typeAliasAnnotationMethodsPhase then
|
||||
stripTypeAliasDeclarationsPhase then
|
||||
provisionalFunctionExpressionPhase then
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.codegen.getNameForDestructuredParameterOrNull
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal val renameAnonymousParametersLowering = makeIrFilePhase(
|
||||
::RenameAnonymousParametersLowering,
|
||||
name = "RenameAnonymousParameters",
|
||||
description = "Mangles variable names for anonymous parameters (only allowed in lambdas)"
|
||||
)
|
||||
|
||||
private class RenameAnonymousParametersLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
|
||||
val oldParameterToNew: MutableMap<IrValueParameter, IrValueParameter> = mutableMapOf()
|
||||
|
||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid()
|
||||
|
||||
override fun visitValueParameter(declaration: IrValueParameter) =
|
||||
declaration.computeNewParameterName()?.let { name ->
|
||||
val descriptor = if (declaration.descriptor is ReceiverParameterDescriptor) {
|
||||
WrappedReceiverParameterDescriptor(declaration.descriptor.annotations)
|
||||
} else {
|
||||
WrappedValueParameterDescriptor(declaration.descriptor.annotations)
|
||||
}
|
||||
IrValueParameterImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
declaration.origin,
|
||||
IrValueParameterSymbolImpl(descriptor),
|
||||
name,
|
||||
declaration.index,
|
||||
declaration.type,
|
||||
declaration.varargElementType,
|
||||
declaration.isCrossinline,
|
||||
declaration.isNoinline
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = declaration.parent
|
||||
defaultValue = declaration.defaultValue
|
||||
annotations += declaration.annotations
|
||||
oldParameterToNew[declaration] = this
|
||||
}
|
||||
} ?: super.visitValueParameter(declaration)
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val oldParameter = expression.symbol.owner
|
||||
return oldParameterToNew[oldParameter]?.let {
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol)
|
||||
} ?: super.visitGetValue(expression)
|
||||
}
|
||||
|
||||
private fun IrValueParameter.computeNewParameterName(): Name? {
|
||||
// Consistent with naming on old (non-IR) backend; see FunctionCodegen.java.
|
||||
descriptor.safeAs<ValueParameterDescriptor>()?.let {
|
||||
getNameForDestructuredParameterOrNull(it)?.let { return Name.identifier(it) }
|
||||
if (DescriptorToSourceUtils.getSourceFromDescriptor(it)?.safeAs<KtParameter>()?.isSingleUnderscore == true) {
|
||||
return Name.identifier("\$noName_${it.index}")
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
data class A(val x: String, val y: Int)
|
||||
|
||||
fun foo(a: A, block: (A) -> String): String = block(a)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
inline fun foo(x: (Int, Station) -> Unit) {
|
||||
x(1, Station(null, "", 1))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
data class A(val x: Double = 1.0, val y: String = "", val z: Char = '0')
|
||||
|
||||
fun foo(a: A, block: (A, String, Int) -> String): String = block(a, "", 1)
|
||||
|
||||
Reference in New Issue
Block a user