diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt index 3b03053cfa0..a2945630b5f 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt @@ -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) { diff --git a/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt index 15e4c2c716c..fad47bd5e27 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt @@ -4,7 +4,7 @@ class Data(val s: T) fun test(d: Data) { if (d.s is String) { - d.s.length + d.s.length } } diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt index d98e52b8cf0..472cdcd7b70 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt @@ -43,6 +43,6 @@ fun test5(x: Inv) { fun test6(x: Inv) { when (val y = x.data) { - is String -> x.data.length // should be ok + is String -> x.data.length // should be ok } }