[K2, MPP] Handle overloaded properties

^KT-57532 Fixed
This commit is contained in:
Ivan Kochurkin
2023-03-23 19:46:40 +01:00
committed by Space Team
parent 43dd8571d3
commit 9a09565cf6
4 changed files with 56 additions and 19 deletions
@@ -163,16 +163,23 @@ private class MemberLinksCollector(
} }
private fun addLink(declaration: IrDeclarationBase) { private fun addLink(declaration: IrDeclarationBase) {
val actualMember = actualMembers.getMatch(declaration, expectActualMap, typeAliasMap) val actualMemberMatches = actualMembers.getMatches(declaration, expectActualMap, typeAliasMap)
if (actualMember != null) { when {
expectActualMap[declaration.symbol] = actualMember.symbol actualMemberMatches.size == 1 -> {
if (declaration is IrProperty) { val actualMember = actualMemberMatches.single()
val actualProperty = actualMember as IrProperty expectActualMap[declaration.symbol] = actualMember.symbol
declaration.getter?.symbol?.let { expectActualMap[it] = actualProperty.getter!!.symbol } if (declaration is IrProperty) {
declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol } 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)
} }
} }
@@ -20,21 +20,29 @@ import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.util.module import org.jetbrains.kotlin.ir.util.module
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun Map<String, List<IrDeclaration>>.getMatch( internal fun Map<String, List<IrDeclaration>>.getMatches(
expectDeclaration: IrDeclaration, expectDeclaration: IrDeclaration,
expectActualTypesMap: Map<IrSymbol, IrSymbol>, expectActualTypesMap: Map<IrSymbol, IrSymbol>,
expectActualTypeAliasMap: Map<FqName, FqName> expectActualTypeAliasMap: Map<FqName, FqName>
): IrDeclaration? { ): List<IrDeclaration> {
val members = this[generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap)] ?: return null val members = this[generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap)] ?: return emptyList()
return if (expectDeclaration is IrFunction) { return when (expectDeclaration) {
members.firstNotNullOfOrNull { runIf(expectDeclaration.match(it as IrFunction, expectActualTypesMap)) { it } } is IrFunction -> members.getMatches(expectDeclaration, expectActualTypesMap) { it as IrFunction }
} else { is IrProperty -> members.getMatches(expectDeclaration, expectActualTypesMap) { (it as IrProperty).getter!! }
members.singleOrNull() else -> members
} }
} }
private inline fun List<IrDeclaration>.getMatches(
expect: IrDeclaration,
expectActualTypesMap: Map<IrSymbol, IrSymbol>,
functionExtractor: (IrDeclaration) -> IrFunction
): List<IrDeclaration> {
val expectFunction = functionExtractor(expect)
return filter { expectFunction.match(functionExtractor(it), expectActualTypesMap) }
}
private fun IrFunction.match(actualFunction: IrFunction, expectActualTypesMap: Map<IrSymbol, IrSymbol>): Boolean { private fun IrFunction.match(actualFunction: IrFunction, expectActualTypesMap: Map<IrSymbol, IrSymbol>): Boolean {
fun getActualizedValueParameterSymbol( fun getActualizedValueParameterSymbol(
expectParameter: IrValueParameter, expectParameter: IrValueParameter,
@@ -83,7 +83,7 @@ class MissingFakeOverridesAdder(
else -> return else -> return
} }
if (members.getMatch(newMember, expectActualMap, typeAliasMap) == null) { if (members.getMatches(newMember, expectActualMap, typeAliasMap).isEmpty()) {
declaration.declarations.add(newMember) declaration.declarations.add(newMember)
members.getOrPut(generateIrElementFullNameFromExpect(newMember, typeAliasMap)) { mutableListOf() }.add(newMember) members.getOrPut(generateIrElementFullNameFromExpect(newMember, typeAliasMap)) { mutableListOf() }.add(newMember)
} else { } else {
@@ -11,8 +11,18 @@ expect fun foo(s: S): S
expect fun foo(i: Int): Int 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 test(s: S) = foo(s)
fun k() = "K".k + "".l
// MODULE: platform()()(common) // MODULE: platform()()(common)
// FILE: platform.kt // FILE: platform.kt
@@ -20,6 +30,18 @@ actual fun foo(i: Int) = i
actual fun foo(s: String) = s 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 actual typealias S = String
fun box() = test("OK") fun box() = test("O") + k()