From 76e132e758ad716cb595df779a77c63021080640 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Tue, 12 Dec 2023 15:13:41 +0100 Subject: [PATCH] [Wasm] Fix overloading virtual methods by vararg and array element type Context: - Kotlin allows functions overloaded with different array element types. - Varargs are lowered to Array parameters. - Before this commit, K/Wasm erased an array element type from the signature, similar to type argument erasure in other cases. Fix: Stop erasing type arguments in arrays when computing v-table signatures. ^KT-58852 Fixed --- .../kotlin/backend/wasm/ir2wasm/ClassInfo.kt | 20 +++++++++++ .../box/functions/kt58825_arrayOverloads.kt | 35 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 compiler/testData/codegen/box/functions/kt58825_arrayOverloads.kt diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt index 0c36dcebc8c..482cec4de4c 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt @@ -54,10 +54,30 @@ private fun IrType.toWasmSignatureType(irBuiltIns: IrBuiltIns): IrType = } private fun IrSimpleType.toWasmSignatureSimpleType(irBuiltIns: IrBuiltIns): IrSimpleType { + // Special case: Kotlin allows overloading functions based on Array type arguments + if (this.classifier == irBuiltIns.arrayClass) { + return irBuiltIns.arrayClass.createType( + hasQuestionMark = isNullable(), + arguments = arguments.map { it.toWasmSignatureTypeArgument(irBuiltIns) } + ) + } + val klass = (this.erasedUpperBound?.symbol ?: irBuiltIns.anyClass).owner return klass.defaultType.withNullability(this.isNullable()) } +private fun IrTypeArgument.toWasmSignatureTypeArgument(irBuiltIns: IrBuiltIns): IrTypeArgument { + return when (this) { + is IrStarProjection -> this + is IrTypeProjection -> { + when (val type = type) { + is IrSimpleType -> type.toWasmSignatureSimpleType(irBuiltIns) + else -> this + } + } + } +} + class VirtualMethodMetadata( val function: IrSimpleFunction, val signature: WasmSignature diff --git a/compiler/testData/codegen/box/functions/kt58825_arrayOverloads.kt b/compiler/testData/codegen/box/functions/kt58825_arrayOverloads.kt new file mode 100644 index 00000000000..bcd4ff2cb21 --- /dev/null +++ b/compiler/testData/codegen/box/functions/kt58825_arrayOverloads.kt @@ -0,0 +1,35 @@ +// WITH_REFLECT + +// Simplified original example from KT-58825 + +import kotlin.reflect.* + +interface DynamicShapeRegister { + fun register(vararg items: KProperty<*>) {} + fun register(vararg items: KCallable<*>) {} +} + +class C : DynamicShapeRegister +val p: Int = 0 + +// Additional tests with nested arrays + +interface ArrayDimensions { + fun getD(x: Array): String = "1D" + fun getD(x: Array>): String = "2D" + fun getD(x: Array>>): String = "3D" + fun getD(x: Array>>>): String = "4D" +} + +fun box(): String { + C().register(::p, ::p) + C().register(::box, ::box, ::C) + + val ad: ArrayDimensions = object : ArrayDimensions {} + check("1D" == ad.getD(arrayOf(1))) + check("2D" == ad.getD(arrayOf(arrayOf(1)))) + check("3D" == ad.getD(arrayOf(arrayOf(arrayOf(1))))) + check("4D" == ad.getD(arrayOf(arrayOf(arrayOf(arrayOf(1)))))) + + return "OK" +} \ No newline at end of file