[FIR] Reuse expect/actual matching data of outer declarations during matching of inner declarations
Review: https://jetbrains.team/p/kt/reviews/13244 Motivation: ``` // Module :lib class Foo { val member: Int = 2 } // Module :app // dependencies { implementation(project(":lib")) } class Foo { val member: Int = 2 } ``` Before the commit: app_Foo.expectForActual is `null` app_Foo.member.expectForActual = lib_foo.member After the commit: app_Foo.expectForActual is `null` app_Foo.member.expectForActual is `null` If I don't fix this problem then `CommonizerHierarchicalIT.testCommonizeHierarchicallyMultiModule` becomes red after I fix KT-59887 in the following commits `app_Foo.member.expectForActual = lib_foo.member` happens because we also need to match fake-overrides (KT-63550) I didn't measure it, but theoretically, this commit should be a performance improvement, becuase we reuse `expectForActual` cache Additionally, The commit breaks some other tests (e.g. compiler/testData/diagnostics/tests/multiplatform/headerClass/actualMissing.fir.kt). The tests will become green again, once I fix KT-59887
This commit is contained in:
+11
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.languageVersionSettings
|
|||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatcherTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatcherTransformer
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
|
|
||||||
internal object LLFirExpectActualMatcherLazyResolver : LLFirLazyResolver(FirResolvePhase.EXPECT_ACTUAL_MATCHING) {
|
internal object LLFirExpectActualMatcherLazyResolver : LLFirLazyResolver(FirResolvePhase.EXPECT_ACTUAL_MATCHING) {
|
||||||
override fun resolve(
|
override fun resolve(
|
||||||
@@ -48,6 +49,16 @@ private class LLFirExpectActualMatchingTargetResolver(
|
|||||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.EXPECT_ACTUAL_MATCHING) {
|
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.EXPECT_ACTUAL_MATCHING) {
|
||||||
private val enabled = session.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
|
private val enabled = session.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
|
||||||
|
|
||||||
|
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||||
|
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||||
|
if (enabled) {
|
||||||
|
// Resolve outer classes before resolving inner declarations. It's the requirement of FirExpectActualResolver
|
||||||
|
firClass.lazyResolveToPhase(resolverPhase.previous)
|
||||||
|
performResolve(firClass)
|
||||||
|
}
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
|
||||||
private val transformer = object : FirExpectActualMatcherTransformer(session, scopeSession) {
|
private val transformer = object : FirExpectActualMatcherTransformer(session, scopeSession) {
|
||||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): FirStatement {
|
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): FirStatement {
|
||||||
transformMemberDeclaration(regularClass)
|
transformMemberDeclaration(regularClass)
|
||||||
|
|||||||
+5
-5
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.fir.resolve.transformers.mpp
|
|||||||
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext
|
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.ExpectForActualMatchingData
|
import org.jetbrains.kotlin.fir.declarations.ExpectForActualMatchingData
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.expectForActual
|
||||||
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||||
@@ -34,15 +34,15 @@ object FirExpectActualResolver {
|
|||||||
is FirCallableSymbol<*> -> {
|
is FirCallableSymbol<*> -> {
|
||||||
val callableId = actualSymbol.callableId
|
val callableId = actualSymbol.callableId
|
||||||
val classId = callableId.classId
|
val classId = callableId.classId
|
||||||
var expectContainingClass: FirRegularClassSymbol? = null
|
|
||||||
var actualContainingClass: FirRegularClassSymbol? = null
|
var actualContainingClass: FirRegularClassSymbol? = null
|
||||||
|
var expectContainingClass: FirRegularClassSymbol? = null
|
||||||
val candidates = when {
|
val candidates = when {
|
||||||
classId != null -> {
|
classId != null -> {
|
||||||
expectContainingClass = useSiteSession.dependenciesSymbolProvider.getClassLikeSymbolByClassId(classId)?.let {
|
|
||||||
it.fullyExpandedClass(it.moduleData.session)
|
|
||||||
}
|
|
||||||
actualContainingClass = useSiteSession.symbolProvider.getClassLikeSymbolByClassId(classId)
|
actualContainingClass = useSiteSession.symbolProvider.getClassLikeSymbolByClassId(classId)
|
||||||
?.fullyExpandedClass(useSiteSession)
|
?.fullyExpandedClass(useSiteSession)
|
||||||
|
expectContainingClass = actualContainingClass?.fir?.expectForActual
|
||||||
|
?.get(ExpectActualMatchingCompatibility.MatchedSuccessfully)
|
||||||
|
?.singleOrNull() as? FirRegularClassSymbol
|
||||||
|
|
||||||
when (actualSymbol) {
|
when (actualSymbol) {
|
||||||
is FirConstructorSymbol -> expectContainingClass?.getConstructors(expectScopeSession)
|
is FirConstructorSymbol -> expectContainingClass?.getConstructors(expectScopeSession)
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ actual class Bar5 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Bar6 {
|
class Bar6 {
|
||||||
actual constructor()
|
<!ACTUAL_WITHOUT_EXPECT!>actual constructor()<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
actual class Bar7 actual constructor(s: String) {
|
actual class Bar7 actual constructor(s: String) {
|
||||||
|
|||||||
+1
-1
@@ -9,5 +9,5 @@ expect class A {
|
|||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
actual fun foo() {}
|
actual fun <!ACTUAL_WITHOUT_EXPECT!>foo<!>() {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user