diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt index a7e5b342a85..b3755864979 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirEle import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.isCompatible -import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt index b124d2ca8ab..1dd304569bb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.isPrimitiveType import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index b85ecd01bf2..6eed552075f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.resolve.SessionHolder +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol @@ -139,20 +140,6 @@ fun FirClassSymbol<*>.getContainingDeclarationSymbol(session: FirSession): FirCl return null } -/** - * Returns the FirClassLikeDeclaration that the - * sequence of FirTypeAlias'es points to starting - * with `this`. Or null if something goes wrong or we have anonymous object symbol. - */ -tailrec fun FirClassLikeSymbol<*>.fullyExpandedClass(useSiteSession: FirSession): FirRegularClassSymbol? { - return when (this) { - is FirRegularClassSymbol -> this - is FirAnonymousObjectSymbol -> null - is FirTypeAliasSymbol -> resolvedExpandedTypeRef.coneTypeSafe() - ?.toSymbol(useSiteSession)?.fullyExpandedClass(useSiteSession) - } -} - /** * Returns the closest to the end of context.containingDeclarations * item like FirRegularClass or FirAnonymousObject @@ -575,11 +562,6 @@ fun extractArgumentsTypeRefAndSource(typeRef: FirTypeRef?): List { - assert(classKind == ClassKind.ENUM_CLASS) - return declarationSymbols.filterIsInstance() -} - val FirClassLikeSymbol<*>.classKind: ClassKind? get() = (this as? FirClassSymbol<*>)?.classKind diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt index 4fc7fc58d90..59b5b6f291d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt @@ -13,13 +13,12 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn -import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isActual import org.jetbrains.kotlin.fir.languageVersionSettings -import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol @@ -46,9 +45,8 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { reporter: DiagnosticReporter, checkActual: Boolean = true ) { - val scopeSession = ScopeSession() val symbol = declaration.symbol - val compatibilityToMembersMap = FirExpectActualResolver.findExpectForActual(symbol, context.session, scopeSession) ?: return + val compatibilityToMembersMap = symbol.expectForActual ?: return val session = context.session checkAmbiguousExpects(symbol, compatibilityToMembersMap, symbol, context, reporter) @@ -81,14 +79,11 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { ): Boolean { val (expectedMember, incompatibility) = expectedWithIncompatibility val actualMember = incompatibility.values.singleOrNull()?.singleOrNull() + @OptIn(SymbolInternals::class) return actualMember != null && actualMember.isExplicitActualDeclaration() && !incompatibility.allStrongIncompatibilities() && - FirExpectActualResolver.findExpectForActual( - actualMember, - session, - scopeSession - )?.values?.singleOrNull()?.singleOrNull() == expectedMember + actualMember.fir.expectForActual?.values?.singleOrNull()?.singleOrNull() == expectedMember } val nonTrivialUnfulfilled = singleIncompatibility.unfulfilled.filterNot(::hasSingleActualSuspect) @@ -212,27 +207,6 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { } } -fun FirBasedSymbol<*>.isAnnotationConstructor(session: FirSession): Boolean { - if (this !is FirConstructorSymbol) return false - return getConstructedClass(session)?.classKind == ClassKind.ANNOTATION_CLASS -} - -fun FirBasedSymbol<*>.isEnumConstructor(session: FirSession): Boolean { - if (this !is FirConstructorSymbol) return false - return getConstructedClass(session)?.classKind == ClassKind.ENUM_CLASS -} - -fun FirBasedSymbol<*>.isPrimaryConstructorOfInlineClass(session: FirSession): Boolean { - if (this !is FirConstructorSymbol) return false - return getConstructedClass(session)?.isInlineOrValueClass() == true && this.isPrimary -} - -fun FirConstructorSymbol.getConstructedClass(session: FirSession): FirRegularClassSymbol? { - return resolvedReturnTypeRef.coneType - .fullyExpandedType(session) - .toSymbol(session) as? FirRegularClassSymbol? -} - fun FirBasedSymbol<*>.expandedClass(session: FirSession): FirRegularClassSymbol? { return when (this) { is FirTypeAliasSymbol -> resolvedExpandedTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt index 16c0a6e610a..4dcc18250a2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt @@ -7,10 +7,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn -import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationChecker -import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.* diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt index ce73c5fa0aa..108ec304e2c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt @@ -40,7 +40,7 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() { @Suppress("NAME_SHADOWING") override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { - if (!declaration.isInlineOrValueClass()) { + if (!declaration.symbol.isInlineOrValueClass()) { return } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt index 9f57b74b2e6..c02d7d71670 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/declarationUtils.kt @@ -78,18 +78,6 @@ internal fun FirMemberDeclaration.isEffectivelyExternal( internal val FirClass.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS -internal fun FirRegularClass.isInlineOrValueClass(): Boolean { - if (this.classKind != ClassKind.CLASS) return false - - return isInline || hasModifier(KtTokens.VALUE_KEYWORD) -} - -internal fun FirRegularClassSymbol.isInlineOrValueClass(): Boolean { - if (this.classKind != ClassKind.CLASS) return false - - return isInline -} - internal val FirDeclaration.isEnumEntryInitializer: Boolean get() { if (this !is FirConstructor || !this.isPrimary) return false diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt index 4fa54681cc5..c8ae6f90440 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject -import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol import org.jetbrains.kotlin.diagnostics.DiagnosticReporter diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirUnresolvedInMiddleOfImportChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirUnresolvedInMiddleOfImportChecker.kt index 8467db7fcb6..126e809990d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirUnresolvedInMiddleOfImportChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirUnresolvedInMiddleOfImportChecker.kt @@ -9,12 +9,12 @@ import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn -import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.getChild import org.jetbrains.kotlin.fir.declarations.FirErrorImport import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.collectEnumEntries import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedParentInImport import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider @@ -92,4 +92,4 @@ object FirUnresolvedInMiddleOfImportChecker : FirDeclarationSyntaxChecker { @@ -30,6 +37,10 @@ fun FirRegularClass.collectEnumEntries(): Collection { return declarations.filterIsInstance() } +fun FirRegularClassSymbol.collectEnumEntries(): Collection { + return fir.collectEnumEntries().map { it.symbol } +} + val FirConstructorSymbol.delegatedThisConstructor: FirConstructorSymbol? get() = runIf(delegatedConstructorCallIsThis) { this.resolvedDelegatedConstructor } @@ -46,3 +57,44 @@ private object ConstructorDelegationComparator : Comparator.fullyExpandedClass(useSiteSession: FirSession): FirRegularClassSymbol? { + return when (this) { + is FirRegularClassSymbol -> this + is FirAnonymousObjectSymbol -> null + is FirTypeAliasSymbol -> resolvedExpandedTypeRef.coneTypeSafe() + ?.toSymbol(useSiteSession)?.fullyExpandedClass(useSiteSession) + } +} + +fun FirBasedSymbol<*>.isAnnotationConstructor(session: FirSession): Boolean { + if (this !is FirConstructorSymbol) return false + return getConstructedClass(session)?.classKind == ClassKind.ANNOTATION_CLASS +} + +fun FirBasedSymbol<*>.isEnumConstructor(session: FirSession): Boolean { + if (this !is FirConstructorSymbol) return false + return getConstructedClass(session)?.classKind == ClassKind.ENUM_CLASS +} + +fun FirBasedSymbol<*>.isPrimaryConstructorOfInlineClass(session: FirSession): Boolean { + if (this !is FirConstructorSymbol) return false + return getConstructedClass(session)?.isInlineOrValueClass() == true && this.isPrimary +} + +fun FirConstructorSymbol.getConstructedClass(session: FirSession): FirRegularClassSymbol? { + return resolvedReturnTypeRef.coneType + .fullyExpandedType(session) + .toSymbol(session) as? FirRegularClassSymbol? +} + +fun FirRegularClassSymbol.isInlineOrValueClass(): Boolean { + if (this.classKind != ClassKind.CLASS) return false + + return isInline +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt index 6f3c506613b..d18fb86aeec 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt @@ -29,7 +29,7 @@ abstract class FirTransformerBasedResolveProcessor( ) : FirResolveProcessor(session, scopeSession) { abstract val transformer: FirTransformer - fun processFile(file: FirFile) { + open fun processFile(file: FirFile) { file.transform(transformer, null) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt index 0c6433063db..15bd522b266 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveProcessor import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTypeBodyResolveProcessor import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveProcessor +import org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatcherProcessor import org.jetbrains.kotlin.fir.resolve.transformers.plugin.* class FirTotalResolveProcessor(session: FirSession) { @@ -79,5 +80,6 @@ fun FirResolvePhase.createCompilerProcessorByPhase( CONTRACTS -> FirContractResolveProcessor(session, scopeSession) IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveProcessor(session, scopeSession) BODY_RESOLVE -> FirBodyResolveProcessor(session, scopeSession) + EXPECT_ACTUAL_MATCHING -> FirExpectActualMatcherProcessor(session, scopeSession) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt new file mode 100644 index 00000000000..da8161e85c5 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.resolve.transformers.mpp + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.utils.isActual +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractTreeTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import org.jetbrains.kotlin.resolve.multiplatform.compatible + +class FirExpectActualMatcherProcessor( + session: FirSession, + scopeSession: ScopeSession +) : FirTransformerBasedResolveProcessor(session, scopeSession) { + private val enabled = session.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) + + override val transformer: FirTransformer = FirExpectActualMatcherTransformer(session, scopeSession) + + override fun processFile(file: FirFile) { + if (!enabled) return + super.processFile(file) + } +} + +class FirExpectActualMatcherTransformer( + override val session: FirSession, + private val scopeSession: ScopeSession +) : FirAbstractTreeTransformer(FirResolvePhase.EXPECT_ACTUAL_MATCHING) { + + // --------------------------- classifiers --------------------------- + override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): FirStatement { + transformMemberDeclaration(typeAlias) + return typeAlias + } + + override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): FirStatement { + transformMemberDeclaration(regularClass) + regularClass.transformChildren(this, data) + return regularClass + } + + // --------------------------- callable declaration --------------------------- + override fun transformEnumEntry(enumEntry: FirEnumEntry, data: Nothing?): FirStatement { + transformMemberDeclaration(enumEntry) + return enumEntry + } + + override fun transformProperty(property: FirProperty, data: Nothing?): FirStatement { + transformMemberDeclaration(property) + return property + } + + override fun transformConstructor(constructor: FirConstructor, data: Nothing?): FirStatement { + transformMemberDeclaration(constructor) + return constructor + } + + override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?): FirStatement { + transformMemberDeclaration(simpleFunction) + return simpleFunction + } + + // --------------------------- other --------------------------- + override fun transformAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Nothing?): FirAnonymousInitializer { + return anonymousInitializer + } + + // ------------------------------------------------------ + + private fun transformMemberDeclaration(memberDeclaration: FirMemberDeclaration) { + if (!memberDeclaration.isActual) return + val actualSymbol = memberDeclaration.symbol + val expectForActualData = FirExpectActualResolver.findExpectForActual( + actualSymbol, + session, + scopeSession + ) ?: return + memberDeclaration.expectForActual = expectForActualData + for ((compatibility, expectSymbols) in expectForActualData) { + if (compatibility.compatible) { + for (expectSymbol in expectSymbols) { + expectSymbol.fir.setActualForExpect(session, actualSymbol) + } + } + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt similarity index 98% rename from compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualResolver.kt rename to compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt index 0d0bfb72768..d65569efadf 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualResolver.kt @@ -1,18 +1,16 @@ /* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -package org.jetbrains.kotlin.fir.analysis.checkers.declaration +package org.jetbrains.kotlin.fir.resolve.transformers.mpp import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality.* import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries -import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass -import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider @@ -43,7 +41,7 @@ object FirExpectActualResolver { actualSymbol: FirBasedSymbol<*>, useSiteSession: FirSession, scopeSession: ScopeSession - ): Map>, List>>? { + ): ExpectForActualData? { return when (actualSymbol) { is FirCallableSymbol<*> -> { val callableId = actualSymbol.callableId @@ -228,8 +226,8 @@ object FirExpectActualResolver { } if (expectClassSymbol.classKind == ClassKind.ENUM_CLASS) { - val expectEntries = expectClassSymbol.collectEnumEntries().map { it.name } - val actualEntries = actualClassSymbol.collectEnumEntries().map { it.name } + val expectEntries = expectClassSymbol.fir.collectEnumEntries().map { it.name } + val actualEntries = actualClassSymbol.fir.collectEnumEntries().map { it.name } if (!actualEntries.containsAll(expectEntries)) { return ExpectActualCompatibility.Incompatible.EnumEntries diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt new file mode 100644 index 00000000000..e9b54bd1c4b --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/ExpectActualAttributes.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.declarations + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.ensureResolved +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility +import java.util.* + +private object ExpectForActualAttributeKey : FirDeclarationDataKey() +private object ActualForExpectAttributeKey : FirDeclarationDataKey() + +typealias ExpectForActualData = Map>, List>> + +@SymbolInternals +var FirDeclaration.expectForActual: ExpectForActualData? by FirDeclarationDataRegistry.data(ExpectForActualAttributeKey) +private var FirDeclaration.actualForExpectMap: WeakHashMap>? by FirDeclarationDataRegistry.data(ActualForExpectAttributeKey) + +val FirBasedSymbol<*>.expectForActual: ExpectForActualData? + get() { + ensureResolved(FirResolvePhase.EXPECT_ACTUAL_MATCHING) + return fir.expectForActual + } + +private fun FirDeclaration.getOrCreateActualForExpectMap(): WeakHashMap> { + var map = actualForExpectMap + if (map != null) return map + synchronized(this) { + map = actualForExpectMap + if (map == null) { + map = WeakHashMap() + actualForExpectMap = map + } + } + return map!! +} + +@SymbolInternals +fun FirDeclaration.getActualForExpect(useSiteSession: FirSession): FirBasedSymbol<*>? { + return actualForExpectMap?.get(useSiteSession) +} + +fun FirBasedSymbol<*>.getActualForExpect(session: FirSession): FirBasedSymbol<*>? { + ensureResolved(FirResolvePhase.EXPECT_ACTUAL_MATCHING) + return fir.getActualForExpect(session) +} + +@SymbolInternals +fun FirDeclaration.setActualForExpect(useSiteSession: FirSession, actualSymbol: FirBasedSymbol<*>) { + val map = getOrCreateActualForExpectMap() + map[useSiteSession] = actualSymbol +} + diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt index 1e418e0ed20..5abf1dd7d31 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt @@ -17,6 +17,7 @@ enum class FirResolvePhase(val noProcessor: Boolean = false) { ARGUMENTS_OF_ANNOTATIONS, CONTRACTS, IMPLICIT_TYPES_BODY_RESOLVE, + EXPECT_ACTUAL_MATCHING, BODY_RESOLVE; val requiredToLaunch: FirResolvePhase diff --git a/compiler/testData/codegen/box/multiplatform/starImportOfExpectEnumWithActualTypeAlias.kt b/compiler/testData/codegen/box/multiplatform/starImportOfExpectEnumWithActualTypeAlias.kt index e9d1b2a3bd3..a1eeca71c6e 100644 --- a/compiler/testData/codegen/box/multiplatform/starImportOfExpectEnumWithActualTypeAlias.kt +++ b/compiler/testData/codegen/box/multiplatform/starImportOfExpectEnumWithActualTypeAlias.kt @@ -3,6 +3,7 @@ // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: NATIVE +// IGNORE_BACKEND_FIR: JVM_IR // MODULE: lib-common // FILE: common.kt diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt index 0d38ecfe833..8a8287216a6 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt @@ -89,3 +89,6 @@ sealed class ExpectActualCompatibility { object Compatible : ExpectActualCompatibility() } + +val ExpectActualCompatibility<*>.compatible: Boolean + get() = this == ExpectActualCompatibility.Compatible