From 2fc5316c1b729e386e2e69679060f490ba2e90ef Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Tue, 23 May 2023 11:50:24 +0200 Subject: [PATCH] [IR] Add a kdoc for IrValueParameter.isHidden --- .../ir/declarations/IrValueParameter.kt | 31 ++++++++++++++ .../jetbrains/kotlin/ir/generator/IrTree.kt | 41 +++++++++++++++---- .../kotlin/ir/generator/config/ConfigModel.kt | 1 + .../kotlin/ir/generator/model/Model.kt | 1 + .../kotlin/ir/generator/print/Common.kt | 11 ++++- .../kotlin/ir/generator/print/Elements.kt | 2 +- .../kotlin/ir/generator/util/Utils.kt | 2 + 7 files changed, 78 insertions(+), 11 deletions(-) diff --git a/compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/declarations/IrValueParameter.kt b/compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/declarations/IrValueParameter.kt index d8e5636b1af..5ea17dcb802 100644 --- a/compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/declarations/IrValueParameter.kt +++ b/compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/declarations/IrValueParameter.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -35,6 +36,36 @@ abstract class IrValueParameter : IrDeclarationBase(), IrValueDeclaration { abstract var isNoinline: Boolean + /** + * If `true`, the value parameter does not participate in [IdSignature] computation. + * + * This is a workaround that is needed for better support of compiler plugins. + * Suppose you have the following code and some IR plugin that adds a value parameter to + * functions + * marked with the `@PluginMarker` annotation. + * ```kotlin + * @PluginMarker + * fun foo(defined: Int) { /* ... */ } + * ``` + * + * Suppose that after applying the plugin the function is changed to: + * ```kotlin + * @PluginMarker + * fun foo(defined: Int, $extra: String) { /* ... */ } + * ``` + * + * If a compiler plugin adds parameters to an [IrFunction], + * the representations of the function in the frontend and in the backend may diverge, + * potentially causing signature mismatch and + * linkage errors (see [KT-40980](https://youtrack.jetbrains.com/issue/KT-40980)). + * We wouldn't want IR plugins to affect the frontend representation, since in an IDE you'd want + * to be able to see those + * declarations in their original form (without the `$extra` parameter). + * + * To fix this problem, [isHidden] was introduced. + * + * TODO: consider dropping [isHidden] if it isn't used by any known plugin. + */ abstract var isHidden: Boolean abstract var defaultValue: IrExpressionBody? diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt index 2d546532aac..7df74734da8 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.ir.generator -import com.squareup.kotlinpoet.FunSpec -import com.squareup.kotlinpoet.PropertySpec -import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.MemberName +import com.squareup.kotlinpoet.* import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.SourceElement @@ -23,6 +20,7 @@ import org.jetbrains.kotlin.ir.generator.config.SimpleFieldConfig import org.jetbrains.kotlin.ir.generator.model.Element.Companion.elementName2typeName import org.jetbrains.kotlin.ir.generator.print.toPoet import org.jetbrains.kotlin.ir.generator.util.* +import org.jetbrains.kotlin.ir.generator.util.Import import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -165,11 +163,36 @@ object IrTree : AbstractTreeBuilder() { +field("varargElementType", irTypeType, nullable = true) +field("isCrossinline", boolean) +field("isNoinline", boolean) - // if true parameter is not included into IdSignature. - // Skipping hidden params makes IrFunction be look similar to FE. - // NOTE: it is introduced to fix KT-40980 because more clear solution was not possible to implement. - // Once we are able to load any top-level declaration from klib this hack should be deprecated and removed. - +field("isHidden", boolean) + +field("isHidden", boolean) { + additionalImports.add(Import("org.jetbrains.kotlin.ir.util", "IdSignature")) + kdoc = """ + If `true`, the value parameter does not participate in [IdSignature] computation. + + This is a workaround that is needed for better support of compiler plugins. + Suppose you have the following code and some IR plugin that adds a value parameter to functions + marked with the `@PluginMarker` annotation. + ```kotlin + @PluginMarker + fun foo(defined: Int) { /* ... */ } + ``` + + Suppose that after applying the plugin the function is changed to: + ```kotlin + @PluginMarker + fun foo(defined: Int, ${'$'}extra: String) { /* ... */ } + ``` + + If a compiler plugin adds parameters to an [${elementName2typeName(function.name)}], + the representations of the function in the frontend and in the backend may diverge, potentially causing signature mismatch and + linkage errors (see [KT-40980](https://youtrack.jetbrains.com/issue/KT-40980)). + We wouldn't want IR plugins to affect the frontend representation, since in an IDE you'd want to be able to see those + declarations in their original form (without the `${'$'}extra` parameter). + + To fix this problem, [$name] was introduced. + + TODO: consider dropping [$name] if it isn't used by any known plugin. + """.trimIndent() + } +field("defaultValue", expressionBody, nullable = true, isChild = true) } val `class`: ElementConfig by element(Declaration) { diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt index 8ffb02de058..f6f3cb34ef0 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt @@ -24,6 +24,7 @@ class ElementConfig( val params = mutableListOf() val parents = mutableListOf() val fields = mutableListOf() + val additionalImports = mutableListOf() var visitorName: String? = null var visitorParent: ElementConfig? = null diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt index dd5af81d7ac..e5a5fd13e39 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt @@ -43,6 +43,7 @@ class Element( val suppressPrint = config.suppressPrint val propertyName = config.propertyName val kDoc = config.kDoc + val additionalImports: List = config.additionalImports override fun toString() = name diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Common.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Common.kt index 084a5104705..ad0d007fb46 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Common.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Common.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.generator.print import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.TypeSpec import org.jetbrains.kotlin.ir.generator.util.GeneratedFile +import org.jetbrains.kotlin.ir.generator.util.Import import java.io.File private val COPYRIGHT by lazy { File("license/COPYRIGHT_HEADER.txt").readText() } @@ -17,8 +18,16 @@ private val GENERATED_MESSAGE = """ """.trimIndent() private val PREFIX by lazy { "$COPYRIGHT\n\n$GENERATED_MESSAGE\n\n" } -fun printTypeCommon(generationPath: File, packageName: String, type: TypeSpec): GeneratedFile { +fun printTypeCommon( + generationPath: File, + packageName: String, + type: TypeSpec, + additionalImports: List = emptyList(), +): GeneratedFile { val code = FileSpec.builder(packageName, type.name!!) + .apply { + additionalImports.forEach { addImport(it.packageName, it.className) } + } .indent(" ") .addType(type) .build() diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt index 8b4e6bd54d9..b7975b9f892 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt @@ -266,7 +266,7 @@ fun printElements(generationPath: File, model: Model) = sequence { element.generationCallback?.invoke(this) }.build() - yield(printTypeCommon(generationPath, elementName.packageName, elementType)) + yield(printTypeCommon(generationPath, elementName.packageName, elementType, element.additionalImports)) } } diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/util/Utils.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/util/Utils.kt index 7232ee582b7..e05a722c7ea 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/util/Utils.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/util/Utils.kt @@ -14,6 +14,8 @@ import java.io.File class GeneratedFile(val file: File, val newText: String) +class Import(val packageName: String, val className: String) + fun ClassName.parameterizedByIfAny(typeArguments: List) = if (typeArguments.isNotEmpty()) parameterizedBy(typeArguments) else this