From ec1ade129302f98bb088798acf9986501e5c4218 Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Wed, 6 Mar 2024 23:09:57 +0100 Subject: [PATCH] [Wasm] Allow virtual functions signature clash for PL support --- .../kotlin/backend/wasm/ir2wasm/ClassInfo.kt | 39 +++++++++---------- .../wasm/ir2wasm/WasmModuleCodegenContext.kt | 7 ++-- 2 files changed, 23 insertions(+), 23 deletions(-) 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 482cec4de4c..e05783e2b52 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 @@ -86,7 +86,8 @@ class VirtualMethodMetadata( class ClassMetadata( val klass: IrClass, val superClass: ClassMetadata?, - irBuiltIns: IrBuiltIns + irBuiltIns: IrBuiltIns, + allowAccidentalOverride: Boolean, ) { // List of all fields including fields of super classes // In Wasm order @@ -102,36 +103,34 @@ class ClassMetadata( val virtualFunctions = klass.declarations .asSequence() .filterVirtualFunctions() - .mapTo(mutableListOf()) { VirtualMethodMetadata(it, it.wasmSignature(irBuiltIns)) } + val virtualFunctionsMetadata = mutableListOf() + val visitedSignature = mutableSetOf() + for (function in virtualFunctions) { + val signature = function.wasmSignature(irBuiltIns) + if (!visitedSignature.add(signature)) { + if (allowAccidentalOverride) { + continue + } else { + val alreadyAdded = virtualFunctionsMetadata.first { it.signature == signature } + error("Class ${klass.fqNameWhenAvailable} has several methods with the same signature $signature\n$alreadyAdded\n$function") + } + } + virtualFunctionsMetadata.add(VirtualMethodMetadata(function, signature)) + } val superClassVirtualMethods = superClass?.virtualMethods - if (superClassVirtualMethods.isNullOrEmpty()) return@run virtualFunctions + if (superClassVirtualMethods.isNullOrEmpty()) return@run virtualFunctionsMetadata val result = mutableListOf() - val signatureToVirtualFunction = virtualFunctions.associateBy { it.signature } + val signatureToVirtualFunction = virtualFunctionsMetadata.associateBy { it.signature } superClassVirtualMethods.mapTo(result) { signatureToVirtualFunction[it.signature] ?: it } val superSignatures = superClassVirtualMethods.mapTo(mutableSetOf()) { it.signature } - virtualFunctions.filterTo(result) { it.signature !in superSignatures } + virtualFunctionsMetadata.filterTo(result) { it.signature !in superSignatures } result } - - init { - val signatureToFunctions = mutableMapOf>() - for (vm in virtualMethods) { - signatureToFunctions.getOrPut(vm.signature) { mutableListOf() }.add(vm.function) - } - - for ((sig, functions) in signatureToFunctions) { - if (functions.size > 1) { - val funcList = functions.joinToString { " ---- ${it.fqNameWhenAvailable} \n" } - // TODO: Check in FE - error("Class ${klass.fqNameWhenAvailable} has ${functions.size} methods with the same signature $sig\n $funcList") - } - } - } } class InterfaceMetadata(val iFace: IrClass, irBuiltIns: IrBuiltIns) { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt index 7e9e84e71a2..361aaff80cf 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt @@ -113,9 +113,10 @@ class WasmModuleCodegenContext( val superClass = irClass.owner.getSuperClass(backendContext.irBuiltIns) val superClassMetadata = superClass?.let { getClassMetadata(it.symbol) } ClassMetadata( - irClass.owner, - superClassMetadata, - backendContext.irBuiltIns + klass = irClass.owner, + superClass = superClassMetadata, + irBuiltIns = backendContext.irBuiltIns, + allowAccidentalOverride = backendContext.partialLinkageSupport.isEnabled ) }