diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualAnnotationMatchingChecker.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualAnnotationMatchingChecker.kt index 0b485d53b34..38204e623c7 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualAnnotationMatchingChecker.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualAnnotationMatchingChecker.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.util.classIdOrFail import org.jetbrains.kotlin.ir.util.isFakeOverride @@ -36,6 +37,9 @@ internal class IrExpectActualAnnotationMatchingChecker( fun check() { for ((expectSymbol, actualSymbol) in matchedExpectToActual.entries) { + if (expectSymbol is IrTypeParameterSymbol) { + continue + } if (expectSymbol.isFakeOverride || actualSymbol.isFakeOverride) { continue } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt index 78dbd0d7cea..48ed5a19d44 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt @@ -5,8 +5,7 @@ package org.jetbrains.kotlin.resolve.calls.mpp -import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker -import org.jetbrains.kotlin.mpp.TypeAliasSymbolMarker +import org.jetbrains.kotlin.mpp.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.checkers.OptInNames @@ -40,15 +39,61 @@ object AbstractExpectActualAnnotationMatchChecker { private fun areAnnotationsCompatible( expectSymbol: DeclarationSymbolMarker, actualSymbol: DeclarationSymbolMarker, + ): Incompatibility? { + return when (expectSymbol) { + is CallableSymbolMarker -> { + areCallableAnnotationsCompatible(expectSymbol, actualSymbol as CallableSymbolMarker) + } + is RegularClassSymbolMarker -> { + areClassAnnotationsCompatible(expectSymbol, actualSymbol as ClassLikeSymbolMarker) + } + else -> error("Incorrect types: $expectSymbol $actualSymbol") + } + } + + context (ExpectActualMatchingContext<*>) + private fun areCallableAnnotationsCompatible( + expectSymbol: CallableSymbolMarker, + actualSymbol: CallableSymbolMarker, + ): Incompatibility? { + commonForClassAndCallableChecks(expectSymbol, actualSymbol)?.let { return it } + + return null + } + + context (ExpectActualMatchingContext<*>) + private fun areClassAnnotationsCompatible( + expectSymbol: RegularClassSymbolMarker, + actualSymbol: ClassLikeSymbolMarker, ): Incompatibility? { if (actualSymbol is TypeAliasSymbolMarker) { val expanded = actualSymbol.expandToRegularClass() ?: return null - return areAnnotationsCompatible(expectSymbol, expanded) + return areClassAnnotationsCompatible(expectSymbol, expanded) } - // TODO(Roman.Efremov, KT-58551): check other annotation targets (constructors, types, value parameters, etc) + commonForClassAndCallableChecks(expectSymbol, actualSymbol)?.let { return it } // TODO(Roman.Efremov, KT-58551): fix actual typealias class members not checked in FE checkers // TODO(Roman.Efremov, KT-58551): check annotations on fake overrides in case of implicit actualization + return null + } + + context (ExpectActualMatchingContext<*>) + private fun commonForClassAndCallableChecks( + expectSymbol: DeclarationSymbolMarker, + actualSymbol: DeclarationSymbolMarker, + ): Incompatibility? { + areAnnotationsSetOnDeclarationsCompatible(expectSymbol, actualSymbol)?.let { return it } + + return null + } + + context (ExpectActualMatchingContext<*>) + private fun areAnnotationsSetOnDeclarationsCompatible( + expectSymbol: DeclarationSymbolMarker, + actualSymbol: DeclarationSymbolMarker, + ): Incompatibility? { + // TODO(Roman.Efremov, KT-58551): check other annotation targets (constructors, types, value parameters, etc) + val skipSourceAnnotations = actualSymbol.hasSourceAnnotationsErased val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }