From 2f00ed3ed781e05b337b4e8a3e61c0023e187542 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 24 Jul 2023 13:27:52 +0200 Subject: [PATCH] [FE] Refactor: reorganize methods in AbstractExpectActualAnnotationMatchChecker Separate callable and class checks to prepare for checking class scopes. Extract common checks to separate methods. Also, it is found that in IR checker annotations on type parameters also checked, because they stored in `matchedExpectToActual`. But it is expected that only classes and callables are checked. This started to fail because of added input parameter type checks inside `areAnnotationsCompatible`. That's why `expectSymbol is IrTypeParameterSymbol` early-return is added. ^KT-60668 ^KT-60936 --- ...IrExpectActualAnnotationMatchingChecker.kt | 4 ++ ...tractExpectActualAnnotationMatchChecker.kt | 53 +++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) 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 }