From 07576b03c46958b78d3dd041305486db86a49748 Mon Sep 17 00:00:00 2001 From: "Evgeniy.Zhelenskiy" Date: Thu, 11 May 2023 21:41:54 +0200 Subject: [PATCH] [IR] Fix inline class constructors having MFVC parameters Signed-off-by: Evgeniy.Zhelenskiy #KT-1179 --- ...LightTreeBlackBoxCodegenTestGenerated.java | 6 +++ .../FirPsiBlackBoxCodegenTestGenerated.java | 6 +++ .../lower/JvmValueClassAbstractLowering.kt | 7 +-- .../kotlin/backend/jvm/InlineClassAbi.kt | 9 +++- .../jvm/MemoizedInlineClassReplacements.kt | 11 ++--- ...emoizedMultiFieldValueClassReplacements.kt | 2 +- .../kotlin/backend/jvm/MfvcNodeFactory.kt | 2 +- .../mfvcAndIcInsideConstructorsOfEachOther.kt | 22 +++++++++ ...mfvcAndIcInsideConstructorsOfEachOther.txt | 48 +++++++++++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ ...kBoxCodegenWithIrInlinerTestGenerated.java | 6 +++ 11 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt create mode 100644 compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.txt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index 38b3fc23aef..00a17a5ba61 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -52089,6 +52089,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/valueClasses/inlineFunctions.kt"); } + @Test + @TestMetadata("mfvcAndIcInsideConstructorsOfEachOther.kt") + public void testMfvcAndIcInsideConstructorsOfEachOther() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt"); + } + @Test @TestMetadata("mfvcBothEqualsOverride.kt") public void testMfvcBothEqualsOverride() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index e7805635098..daa1a47d8e4 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -52089,6 +52089,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/valueClasses/inlineFunctions.kt"); } + @Test + @TestMetadata("mfvcAndIcInsideConstructorsOfEachOther.kt") + public void testMfvcAndIcInsideConstructorsOfEachOther() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt"); + } + @Test @TestMetadata("mfvcBothEqualsOverride.kt") public void testMfvcBothEqualsOverride() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt index 5f0ddf64575..0bd5722cf08 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt @@ -8,18 +8,12 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.jvm.* -import org.jetbrains.kotlin.backend.jvm.ir.isValueClassType -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.transformStatement -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.isNothing -import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name @@ -192,6 +186,7 @@ internal abstract class JvmValueClassAbstractLowering( replacement, when { function.isValueClassTypedEquals -> InlineClassAbi.mangledNameFor( + context, function, mangleReturnTypes = false, useOldMangleRules = false diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/InlineClassAbi.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/InlineClassAbi.kt index 1faa2eb3cb2..6ffbfe7cef2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/InlineClassAbi.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/InlineClassAbi.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.backend.jvm +import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType import org.jetbrains.kotlin.backend.jvm.ir.isValueClassType @@ -58,7 +59,7 @@ object InlineClassAbi { * Returns a mangled name for a function taking inline class arguments * to avoid clashes between overloaded methods. */ - fun mangledNameFor(irFunction: IrFunction, mangleReturnTypes: Boolean, useOldMangleRules: Boolean): Name { + fun mangledNameFor(context: JvmBackendContext, irFunction: IrFunction, mangleReturnTypes: Boolean, useOldMangleRules: Boolean): Name { if (irFunction is IrConstructor) { // Note that we might drop this convention and use standard mangling for constructors too, see KT-37186. assert(irFunction.constructedClass.isValue) { @@ -66,6 +67,9 @@ object InlineClassAbi { } return Name.identifier("constructor-impl") } + if (irFunction.isAlreadyMangledMfvcFunction(context)) { + return irFunction.name + } val suffix = hashSuffix(irFunction, mangleReturnTypes, useOldMangleRules) if (suffix == null && ((irFunction.parent as? IrClass)?.isValue != true || irFunction.origin == IrDeclarationOrigin.IR_BUILTINS_STUB)) { @@ -86,6 +90,9 @@ object InlineClassAbi { return Name.identifier("$base-${suffix ?: "impl"}") } + private fun IrFunction.isAlreadyMangledMfvcFunction(context: JvmBackendContext) = + context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure[this]?.any { it is MultiFieldValueClassMapping } == true + fun hashSuffix(irFunction: IrFunction, mangleReturnTypes: Boolean, useOldMangleRules: Boolean): String? = hashSuffix( useOldMangleRules, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt index 110206ec93e..274e2fc7921 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt @@ -5,7 +5,10 @@ package org.jetbrains.kotlin.backend.jvm -import org.jetbrains.kotlin.backend.jvm.ir.* +import org.jetbrains.kotlin.backend.jvm.ir.classFileContainsMethod +import org.jetbrains.kotlin.backend.jvm.ir.extensionReceiverName +import org.jetbrains.kotlin.backend.jvm.ir.isStaticValueClassReplacement +import org.jetbrains.kotlin.backend.jvm.ir.parentClassId import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality @@ -13,11 +16,8 @@ import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl -import org.jetbrains.kotlin.ir.types.isNothing -import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver @@ -46,7 +46,6 @@ class MemoizedInlineClassReplacements( (it.isLocal && it is IrSimpleFunction && it.overriddenSymbols.isEmpty()) || (it.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR && it.visibility == DescriptorVisibilities.LOCAL) || it.isStaticValueClassReplacement || - it in context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure || it.origin == JvmLoweredDeclarationOrigin.MULTI_FIELD_VALUE_CLASS_GENERATED_IMPL_METHOD || it.origin.isSynthetic && it.origin != IrDeclarationOrigin.SYNTHETIC_GENERATED_SAM_IMPLEMENTATION -> null @@ -246,7 +245,7 @@ class MemoizedInlineClassReplacements( else -> replacementOrigin } - name = InlineClassAbi.mangledNameFor(function, mangleReturnTypes, useOldManglingScheme) + name = InlineClassAbi.mangledNameFor(context, function, mangleReturnTypes, useOldManglingScheme) } override fun getReplacementForRegularClassConstructor(constructor: IrConstructor): IrConstructor? = null diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt index 54cf13f7e7d..23145babcb5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt @@ -108,7 +108,7 @@ class MemoizedMultiFieldValueClassReplacements( } name = if (function.isLocal && (function !is IrSimpleFunction || function.overriddenSymbols.isEmpty())) function.name - else InlineClassAbi.mangledNameFor(function, mangleReturnTypes = false, useOldMangleRules = false) + else InlineClassAbi.mangledNameFor(context, function, mangleReturnTypes = false, useOldMangleRules = false) } private fun makeAndAddGroupedValueParametersFrom( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt index cf837442e6b..c3d82e8053e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt @@ -460,7 +460,7 @@ private fun makePrimaryConstructorImpl( leaves: List, subnodes: List, ) = context.irFactory.buildFun { - name = InlineClassAbi.mangledNameFor(oldPrimaryConstructor, false, false) + name = InlineClassAbi.mangledNameFor(context, oldPrimaryConstructor, false, false) visibility = oldPrimaryConstructor.visibility origin = JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_CONSTRUCTOR returnType = context.irBuiltIns.unitType diff --git a/compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt b/compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt new file mode 100644 index 00000000000..f18539649b7 --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt @@ -0,0 +1,22 @@ +// LANGUAGE: +ValueClasses +// TARGET_BACKEND: JVM_IR +// CHECK_BYTECODE_LISTING +// WITH_STDLIB +// CHECK_BYTECODE_TEXT +// FIR_IDENTICAL + +@JvmInline +value class IC(val x: Int) { + constructor(mfvc: MFVC) : this(mfvc.x + mfvc.y) +} + +@JvmInline +value class MFVC(val x: Int, val y: Int) { + constructor(ic: IC) : this(ic.x, ic.x) +} + +fun box(): String { + require(IC(MFVC(1, 2)) == IC(3)) + require(MFVC(IC(1)) == MFVC(1, 1)) + return "OK" +} diff --git a/compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.txt b/compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.txt new file mode 100644 index 00000000000..5d7be13ea68 --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.txt @@ -0,0 +1,48 @@ +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class IC { + // source: 'mfvcAndIcInsideConstructorsOfEachOther.kt' + private final field x: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): IC + public static method constructor-impl(p0: int): int + public static method constructor-impl(p0: int, p1: int): int + public method equals(p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: java.lang.Object): boolean + public final static method equals-impl0(p0: int, p1: int): boolean + public final method getX(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class MFVC { + // source: 'mfvcAndIcInsideConstructorsOfEachOther.kt' + private final field x: int + private final field y: int + private synthetic method (p0: int, p1: int): void + public synthetic final static method box-impl(p0: int, p1: int): MFVC + public final static @org.jetbrains.annotations.NotNull method constructor-impl(p0: int): MFVC + public final static method constructor-impl(p0: int, p1: int): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: int, p2: java.lang.Object): boolean + public final static method equals-impl0(p0: int, p1: int, p2: int, p3: int): boolean + public final method getX(): int + public final method getY(): int + public method hashCode(): int + public static method hashCode-impl(p0: int, p1: int): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public static method toString-impl(p0: int, p1: int): java.lang.String + public synthetic final method unbox-impl-x(): int + public synthetic final method unbox-impl-y(): int +} + +@kotlin.Metadata +public final class MfvcAndIcInsideConstructorsOfEachOtherKt { + // source: 'mfvcAndIcInsideConstructorsOfEachOther.kt' + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index ee3cfcf901f..f39dc7f7189 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -52089,6 +52089,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/valueClasses/inlineFunctions.kt"); } + @Test + @TestMetadata("mfvcAndIcInsideConstructorsOfEachOther.kt") + public void testMfvcAndIcInsideConstructorsOfEachOther() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt"); + } + @Test @TestMetadata("mfvcBothEqualsOverride.kt") public void testMfvcBothEqualsOverride() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index 149bc5c825f..02184fb65a8 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -52089,6 +52089,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/valueClasses/inlineFunctions.kt"); } + @Test + @TestMetadata("mfvcAndIcInsideConstructorsOfEachOther.kt") + public void testMfvcAndIcInsideConstructorsOfEachOther() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/mfvcAndIcInsideConstructorsOfEachOther.kt"); + } + @Test @TestMetadata("mfvcBothEqualsOverride.kt") public void testMfvcBothEqualsOverride() throws Exception {