[IR] Fix inline class constructors having MFVC parameters

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2023-05-11 21:41:54 +02:00
committed by Space Team
parent 2535a87f85
commit 07576b03c4
11 changed files with 110 additions and 15 deletions
@@ -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 {
@@ -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 {
@@ -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
@@ -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,
@@ -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
@@ -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(
@@ -460,7 +460,7 @@ private fun makePrimaryConstructorImpl(
leaves: List<LeafMfvcNode>,
subnodes: List<NameableMfvcNode>,
) = 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
@@ -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"
}
@@ -0,0 +1,48 @@
@kotlin.jvm.JvmInline
@kotlin.Metadata
public final class IC {
// source: 'mfvcAndIcInsideConstructorsOfEachOther.kt'
private final field x: int
private synthetic method <init>(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 <init>(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
}
@@ -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 {
@@ -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 {