[FIR] Extract expect actual matching into separate phase

This commit is contained in:
Dmitriy Novozhilov
2022-04-08 17:48:03 +04:00
committed by teamcity
parent de842817e8
commit d66748d011
18 changed files with 235 additions and 79 deletions
@@ -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
@@ -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
@@ -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<ConeClassLikeType>()
?.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<FirTypeRefSourc
data class FirTypeRefSource(val typeRef: FirTypeRef?, val source: KtSourceElement?)
fun FirRegularClassSymbol.collectEnumEntries(): Collection<FirEnumEntrySymbol> {
assert(classKind == ClassKind.ENUM_CLASS)
return declarationSymbols.filterIsInstance<FirEnumEntrySymbol>()
}
val FirClassLikeSymbol<*>.classKind: ClassKind?
get() = (this as? FirClassSymbol<*>)?.classKind
@@ -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
@@ -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.*
@@ -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
}
@@ -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
@@ -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
@@ -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<FirFil
private fun KtSourceElement.dotQualifiedExpression() = getChild(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, depth = 1)
private fun KtSourceElement.selectorExpression() = getChild(KtNodeTypes.REFERENCE_EXPRESSION, depth = 1, reverse = true)
}
}
@@ -7,8 +7,15 @@ package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun FirClass.constructors(session: FirSession): List<FirConstructorSymbol> {
@@ -30,6 +37,10 @@ fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
return declarations.filterIsInstance<FirEnumEntry>()
}
fun FirRegularClassSymbol.collectEnumEntries(): Collection<FirEnumEntrySymbol> {
return fir.collectEnumEntries().map { it.symbol }
}
val FirConstructorSymbol.delegatedThisConstructor: FirConstructorSymbol?
get() = runIf(delegatedConstructorCallIsThis) { this.resolvedDelegatedConstructor }
@@ -46,3 +57,44 @@ private object ConstructorDelegationComparator : Comparator<FirConstructorSymbol
return 0
}
}
/**
* 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<ConeClassLikeType>()
?.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
}
@@ -29,7 +29,7 @@ abstract class FirTransformerBasedResolveProcessor(
) : FirResolveProcessor(session, scopeSession) {
abstract val transformer: FirTransformer<Nothing?>
fun processFile(file: FirFile) {
open fun processFile(file: FirFile) {
file.transform<FirFile, Nothing?>(transformer, null)
}
}
@@ -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)
}
}
@@ -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<Nothing?> = 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<Nothing?>(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)
}
}
}
}
}
@@ -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<ExpectActualCompatibility<FirBasedSymbol<*>>, List<FirBasedSymbol<*>>>? {
): 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
@@ -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<ExpectActualCompatibility<FirBasedSymbol<*>>, List<FirBasedSymbol<*>>>
@SymbolInternals
var FirDeclaration.expectForActual: ExpectForActualData? by FirDeclarationDataRegistry.data(ExpectForActualAttributeKey)
private var FirDeclaration.actualForExpectMap: WeakHashMap<FirSession, FirBasedSymbol<*>>? by FirDeclarationDataRegistry.data(ActualForExpectAttributeKey)
val FirBasedSymbol<*>.expectForActual: ExpectForActualData?
get() {
ensureResolved(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
return fir.expectForActual
}
private fun FirDeclaration.getOrCreateActualForExpectMap(): WeakHashMap<FirSession, FirBasedSymbol<*>> {
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
}
@@ -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
@@ -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
@@ -89,3 +89,6 @@ sealed class ExpectActualCompatibility<out D> {
object Compatible : ExpectActualCompatibility<Nothing>()
}
val ExpectActualCompatibility<*>.compatible: Boolean
get() = this == ExpectActualCompatibility.Compatible