K2: Unwrap fake overrides before using them as DFA identifiers

It's necessary because even for stable a.b.c.d we can't guarantee that
this reference will always point to the same symbol because
different capture type instantiations generate different scopes
with different resulting symbol instances.
This commit is contained in:
Denis.Zharkov
2022-12-07 15:43:48 +01:00
committed by Space Team
parent 9af3e5704d
commit a4c5e1bc87
3 changed files with 19 additions and 5 deletions
@@ -12,9 +12,13 @@ import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirThisReference import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeContext
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
fun TypeStatement?.smartCastedType(context: ConeTypeContext, originalType: ConeKotlinType): ConeKotlinType = fun TypeStatement?.smartCastedType(context: ConeTypeContext, originalType: ConeKotlinType): ConeKotlinType =
if (this != null && exactType.isNotEmpty()) { if (this != null && exactType.isNotEmpty()) {
@@ -39,9 +43,9 @@ val FirExpression.coneType: ConeKotlinType
@DfaInternals @DfaInternals
val FirElement.symbol: FirBasedSymbol<*>? val FirElement.symbol: FirBasedSymbol<*>?
get() = when (this) { get() = when (this) {
is FirResolvable -> symbol is FirResolvable -> symbol.unwrapFakeOverridesIfNecessary()
is FirVariableAssignment -> unwrapLValue()?.symbol is FirVariableAssignment -> unwrapLValue()?.symbol
is FirDeclaration -> symbol is FirDeclaration -> symbol.unwrapFakeOverridesIfNecessary()
is FirWhenSubjectExpression -> whenRef.value.subject?.symbol is FirWhenSubjectExpression -> whenRef.value.subject?.symbol
is FirSafeCallExpression -> selector.symbol is FirSafeCallExpression -> selector.symbol
is FirSmartCastExpression -> originalExpression.symbol is FirSmartCastExpression -> originalExpression.symbol
@@ -52,6 +56,16 @@ val FirElement.symbol: FirBasedSymbol<*>?
(it !is FirFunctionSymbol<*> && it !is FirSyntheticPropertySymbol) (it !is FirFunctionSymbol<*> && it !is FirSyntheticPropertySymbol)
} }
private fun FirBasedSymbol<*>?.unwrapFakeOverridesIfNecessary(): FirBasedSymbol<*>? {
if (this !is FirCallableSymbol) return this
// This is necessary only for sake of optimizations necessary because this is a really hot place.
// Not having `dispatchReceiverType` means that this is a local/top-level property that can't be a fake override.
// And at the same time, checking a field is much faster than a couple of attributes (0.3 secs at MT Full Kotlin)
if (this.dispatchReceiverType == null) return this
return this.unwrapFakeOverrides()
}
@DfaInternals @DfaInternals
internal val FirResolvable.symbol: FirBasedSymbol<*>? internal val FirResolvable.symbol: FirBasedSymbol<*>?
get() = when (val reference = calleeReference) { get() = when (val reference = calleeReference) {
@@ -4,7 +4,7 @@ class Data<T>(val s: T)
fun test(d: Data<out Any>) { fun test(d: Data<out Any>) {
if (d.s is String) { if (d.s is String) {
d.s.<!UNRESOLVED_REFERENCE!>length<!> d.s.length
} }
} }
@@ -43,6 +43,6 @@ fun test5(x: Inv<out Any?>) {
fun test6(x: Inv<out String?>) { fun test6(x: Inv<out String?>) {
when (val y = x.data) { when (val y = x.data) {
is String -> x.data<!UNSAFE_CALL!>.<!>length // should be ok is String -> x.data.length // should be ok
} }
} }