diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt index fa14088908e..b7b1b6179c3 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt @@ -163,16 +163,23 @@ private class MemberLinksCollector( } private fun addLink(declaration: IrDeclarationBase) { - val actualMember = actualMembers.getMatch(declaration, expectActualMap, typeAliasMap) - if (actualMember != null) { - expectActualMap[declaration.symbol] = actualMember.symbol - if (declaration is IrProperty) { - val actualProperty = actualMember as IrProperty - declaration.getter?.symbol?.let { expectActualMap[it] = actualProperty.getter!!.symbol } - declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol } + val actualMemberMatches = actualMembers.getMatches(declaration, expectActualMap, typeAliasMap) + when { + actualMemberMatches.size == 1 -> { + val actualMember = actualMemberMatches.single() + expectActualMap[declaration.symbol] = actualMember.symbol + if (declaration is IrProperty) { + val actualProperty = actualMember as IrProperty + declaration.getter!!.symbol.let { expectActualMap[it] = actualProperty.getter!!.symbol } + declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol } + } + } + actualMemberMatches.size > 1 -> { + // TODO: report AMBIGUOUS_ACTUALS here, see KT-57932 + } + !declaration.parent.containsOptionalExpectation() && !(declaration is IrConstructor && declaration.isPrimary) -> { + diagnosticsReporter.reportMissingActual(declaration) } - } else if (!declaration.parent.containsOptionalExpectation() && !(declaration is IrConstructor && declaration.isPrimary)) { - diagnosticsReporter.reportMissingActual(declaration) } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt index e14be4e6f4b..57f0519faec 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt @@ -20,21 +20,29 @@ import org.jetbrains.kotlin.ir.util.kotlinFqName import org.jetbrains.kotlin.ir.util.module import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil -import org.jetbrains.kotlin.utils.addToStdlib.runIf -fun Map>.getMatch( +internal fun Map>.getMatches( expectDeclaration: IrDeclaration, expectActualTypesMap: Map, expectActualTypeAliasMap: Map -): IrDeclaration? { - val members = this[generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap)] ?: return null - return if (expectDeclaration is IrFunction) { - members.firstNotNullOfOrNull { runIf(expectDeclaration.match(it as IrFunction, expectActualTypesMap)) { it } } - } else { - members.singleOrNull() +): List { + val members = this[generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap)] ?: return emptyList() + return when (expectDeclaration) { + is IrFunction -> members.getMatches(expectDeclaration, expectActualTypesMap) { it as IrFunction } + is IrProperty -> members.getMatches(expectDeclaration, expectActualTypesMap) { (it as IrProperty).getter!! } + else -> members } } +private inline fun List.getMatches( + expect: IrDeclaration, + expectActualTypesMap: Map, + functionExtractor: (IrDeclaration) -> IrFunction +): List { + val expectFunction = functionExtractor(expect) + return filter { expectFunction.match(functionExtractor(it), expectActualTypesMap) } +} + private fun IrFunction.match(actualFunction: IrFunction, expectActualTypesMap: Map): Boolean { fun getActualizedValueParameterSymbol( expectParameter: IrValueParameter, diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/MissingFakeOverridesAdder.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/MissingFakeOverridesAdder.kt index d1fa846fd39..73c369ec4cc 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/MissingFakeOverridesAdder.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/MissingFakeOverridesAdder.kt @@ -83,7 +83,7 @@ class MissingFakeOverridesAdder( else -> return } - if (members.getMatch(newMember, expectActualMap, typeAliasMap) == null) { + if (members.getMatches(newMember, expectActualMap, typeAliasMap).isEmpty()) { declaration.declarations.add(newMember) members.getOrPut(generateIrElementFullNameFromExpect(newMember, typeAliasMap)) { mutableListOf() }.add(newMember) } else { diff --git a/compiler/testData/codegen/box/multiplatform/k2/basic/expectActualOverloads.kt b/compiler/testData/codegen/box/multiplatform/k2/basic/expectActualOverloads.kt index c25380bc758..724a278ae2d 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/basic/expectActualOverloads.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/basic/expectActualOverloads.kt @@ -11,8 +11,18 @@ expect fun foo(s: S): S expect fun foo(i: Int): Int +expect val Int.k: Int + +expect val String.k: String + +expect var Int.l: Int + +expect var String.l: String + fun test(s: S) = foo(s) +fun k() = "K".k + "".l + // MODULE: platform()()(common) // FILE: platform.kt @@ -20,6 +30,18 @@ actual fun foo(i: Int) = i actual fun foo(s: String) = s +actual val Int.k: Int get() = 42 + +actual val String.k: String get() = this + +actual var Int.l: Int + get() = 48 + set(value) {} + +actual var String.l: String + get() = this + set(value) {} + actual typealias S = String -fun box() = test("OK") \ No newline at end of file +fun box() = test("O") + k() \ No newline at end of file