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:
committed by
Space Team
parent
9af3e5704d
commit
a4c5e1bc87
@@ -12,9 +12,13 @@ import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
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.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 =
|
||||
if (this != null && exactType.isNotEmpty()) {
|
||||
@@ -39,9 +43,9 @@ val FirExpression.coneType: ConeKotlinType
|
||||
@DfaInternals
|
||||
val FirElement.symbol: FirBasedSymbol<*>?
|
||||
get() = when (this) {
|
||||
is FirResolvable -> symbol
|
||||
is FirResolvable -> symbol.unwrapFakeOverridesIfNecessary()
|
||||
is FirVariableAssignment -> unwrapLValue()?.symbol
|
||||
is FirDeclaration -> symbol
|
||||
is FirDeclaration -> symbol.unwrapFakeOverridesIfNecessary()
|
||||
is FirWhenSubjectExpression -> whenRef.value.subject?.symbol
|
||||
is FirSafeCallExpression -> selector.symbol
|
||||
is FirSmartCastExpression -> originalExpression.symbol
|
||||
@@ -52,6 +56,16 @@ val FirElement.symbol: FirBasedSymbol<*>?
|
||||
(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
|
||||
internal val FirResolvable.symbol: FirBasedSymbol<*>?
|
||||
get() = when (val reference = calleeReference) {
|
||||
|
||||
@@ -4,7 +4,7 @@ class Data<T>(val s: T)
|
||||
|
||||
fun test(d: Data<out Any>) {
|
||||
if (d.s is String) {
|
||||
d.s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
d.s.length
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -43,6 +43,6 @@ fun test5(x: Inv<out Any?>) {
|
||||
|
||||
fun test6(x: Inv<out String?>) {
|
||||
when (val y = x.data) {
|
||||
is String -> x.data<!UNSAFE_CALL!>.<!>length // should be ok
|
||||
is String -> x.data.length // should be ok
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user