~ WIP
diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/RefinedTypeForDataFlowTypeAttribute.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/RefinedTypeForDataFlowTypeAttribute.kt
new file mode 100644
index 0000000..a7d30fb
--- /dev/null
+++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/RefinedTypeForDataFlowTypeAttribute.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2025 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.types
+
+import kotlin.reflect.KClass
+
+/**
+ * [RefinedTypeForDataFlowTypeAttribute] stores the abbreviated type ([coneType]) of its owning expanded type. In the compiler, it is used exclusively
+ * for rendering the abbreviated typed in place of the expanded type. The Analysis API uses this attribute for additional purposes such as
+ * navigation to the type alias.
+ *
+ * The abbreviated type may not always be resolvable from a use-site session. For example, the owning expanded type may come from a library
+ * `L2` with a dependency on another library `L1` containing the type alias declaration. If the use-site session depends on `L2` but not on
+ * `L1`, the abbreviated type won't be resolvable even if the expanded type is.
+ */
+class RefinedTypeForDataFlowTypeAttribute(
+    override val coneType: ConeKotlinType,
+) : ConeAttributeWithConeType<RefinedTypeForDataFlowTypeAttribute>() {
+    override fun union(other: RefinedTypeForDataFlowTypeAttribute?): RefinedTypeForDataFlowTypeAttribute? = null
+    override fun intersect(other: RefinedTypeForDataFlowTypeAttribute?): RefinedTypeForDataFlowTypeAttribute? = null
+    override fun add(other: RefinedTypeForDataFlowTypeAttribute?): RefinedTypeForDataFlowTypeAttribute = other ?: this
+    override fun isSubtypeOf(other: RefinedTypeForDataFlowTypeAttribute?): Boolean = true
+    override fun toString(): String = "{${coneType.renderForDebugging()}=}"
+    override fun copyWith(newType: ConeKotlinType): RefinedTypeForDataFlowTypeAttribute = RefinedTypeForDataFlowTypeAttribute(newType)
+
+    override val key: KClass<out RefinedTypeForDataFlowTypeAttribute>
+        get() = RefinedTypeForDataFlowTypeAttribute::class
+    override val keepInInferredDeclarationType: Boolean
+        get() = true
+}
+
+val ConeAttributes.refinedTypeForDataFlow: RefinedTypeForDataFlowTypeAttribute? by ConeAttributes.attributeAccessor<RefinedTypeForDataFlowTypeAttribute>()
+
+val ConeKotlinType.refinedTypeForDataFlowOrSelf: ConeKotlinType
+    get() = attributes.refinedTypeForDataFlow?.coneType ?: this
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt
index 02b697f..8685e68 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt
@@ -246,10 +246,6 @@
      * @See org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createKnownTypeParameterSubstitutorForSpecialCall
      */
     private fun Candidate.isSyntheticFunctionCallThatShouldUseEqualityConstraint(expectedType: ConeKotlinType): Boolean {
-        // If we're inside an assignment's RHS, we mustn't add an equality constraint because it might prevent smartcasts.
-        // Example: val x: String? = null; x = if (foo) "" else throw Exception()
-        if (components.context.isInsideAssignmentRhs) return false
-
         val symbol = symbol as? FirCallableSymbol ?: return false
         if (symbol.origin != FirDeclarationOrigin.Synthetic.FakeFunction ||
             expectedType.isUnitOrAnyWithArbitraryNullability() ||
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
index e189c44..ce573d9 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
@@ -57,6 +57,7 @@
 import org.jetbrains.kotlin.fir.visitors.FirTransformer
 import org.jetbrains.kotlin.fir.visitors.TransformData
 import org.jetbrains.kotlin.fir.visitors.transformSingle
+import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
 import org.jetbrains.kotlin.resolve.calls.inference.model.InferredEmptyIntersection
 import org.jetbrains.kotlin.resolve.calls.tower.ApplicabilityDetail
 import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
@@ -1137,22 +1138,52 @@
         data: ExpectedArgumentType?,
     ): FirStatement {
         return transformSyntheticCall(whenExpression, data).apply {
+            if (isProperlyExhaustive) {
+                extracted(this, branches.map { it.result.resultType })
+            }
             replaceReturnTypeIfNotExhaustive(session)
         }
     }
 
+    private fun extracted(expression: FirExpression, branchesTypes: List<ConeKotlinType>) {
+        val refinedTypeForDataFlow = with(NewCommonSuperTypeCalculator) {
+            with(session.typeContext) {
+                commonSuperType(branchesTypes)
+            }
+        } as ConeKotlinType
+
+        val currentType = expression.resultType
+        if (!refinedTypeForDataFlow.isUnitOrFlexibleUnit && !currentType.isUnitOrFlexibleUnit &&
+            !currentType.isSubtypeOf(refinedTypeForDataFlow, session)
+        ) {
+            expression.resultType = currentType.withAttributes(
+                currentType.attributes.add(RefinedTypeForDataFlowTypeAttribute(refinedTypeForDataFlow))
+            )
+        }
+    }
+
     override fun transformTryExpression(
         tryExpression: FirTryExpression,
         data: ExpectedArgumentType?,
     ): FirStatement {
-        return transformSyntheticCall(tryExpression, data)
+        return transformSyntheticCall(tryExpression, data).also { transformed ->
+            extracted(
+                transformed,
+                buildList {
+                    add(transformed.tryBlock.resultType)
+                    transformed.catches.mapTo(this) { it.block.resultType }
+                }
+            )
+        }
     }
 
     override fun transformCheckNotNullCall(
         checkNotNullCall: FirCheckNotNullCall,
         data: ExpectedArgumentType?,
     ): FirStatement {
-        return transformSyntheticCall(checkNotNullCall, data)
+        return transformSyntheticCall(checkNotNullCall, data).also {
+            extracted(it, listOf(it.argumentList.arguments[0].resultType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)))
+        }
     }
 
     override fun transformElvisExpression(
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt
index 78287c3..1890119 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt
@@ -84,20 +84,6 @@
     @set:PrivateForInline
     var inferenceSession: FirInferenceSession = FirInferenceSession.DEFAULT
 
-    @set:PrivateForInline
-    var isInsideAssignmentRhs: Boolean = false
-
-    @OptIn(PrivateForInline::class)
-    inline fun <R> withAssignmentRhs(block: () -> R): R {
-        val oldMode = this.isInsideAssignmentRhs
-        this.isInsideAssignmentRhs = true
-        return try {
-            block()
-        } finally {
-            this.isInsideAssignmentRhs = oldMode
-        }
-    }
-
     @OptIn(PrivateForInline::class)
     inline fun withClassHeader(clazz: FirRegularClass, action: () -> Unit) {
         withSwitchedTowerDataModeForStaticNestedClass(clazz) {
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
index 33da4ce..9005c2f 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
@@ -1300,14 +1300,12 @@
             }
         }
 
-        val result = context.withAssignmentRhs {
-            variableAssignment.transformRValue(
-                transformer,
-                withExpectedType(
-                    variableAssignment.lValue.resolvedType.toFirResolvedTypeRef(),
-                ),
-            )
-        }
+        val result = variableAssignment.transformRValue(
+            transformer,
+            withExpectedType(
+                variableAssignment.lValue.resolvedType.toFirResolvedTypeRef(),
+            ),
+        )
 
         // for cases like
         // buildSomething { tVar = "" // Should infer TV from String assignment }
diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/model.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/model.kt
index 5e64eb3..ca0da559 100644
--- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/model.kt
+++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/model.kt
@@ -10,6 +10,7 @@
 import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
 import org.jetbrains.kotlin.fir.types.ConeErrorType
 import org.jetbrains.kotlin.fir.types.ConeKotlinType
+import org.jetbrains.kotlin.fir.types.refinedTypeForDataFlowOrSelf
 import kotlin.contracts.ExperimentalContracts
 import kotlin.contracts.contract
 
@@ -53,7 +54,7 @@
     MutableTypeStatement(this, lowerTypes = linkedSetOf(DfaType.BooleanLiteral(boolean)))
 
 infix fun RealVariable.typeEq(type: ConeKotlinType): MutableTypeStatement =
-    MutableTypeStatement(this, if (type is ConeErrorType) linkedSetOf() else linkedSetOf(type))
+    MutableTypeStatement(this, if (type is ConeErrorType) linkedSetOf() else linkedSetOf(type.refinedTypeForDataFlowOrSelf))
 
 infix fun RealVariable.typeNotEq(type: ConeKotlinType): MutableTypeStatement =
     MutableTypeStatement(this, lowerTypes = if (type is ConeErrorType) linkedSetOf() else linkedSetOf(DfaType.Cone(type)))
diff --git a/compiler/testData/codegen/box/inference/ifWithAssignmentAndNothingBranch.kt b/compiler/testData/codegen/box/inference/ifWithAssignmentAndNothingBranch.kt
index 16d8552..59f03b9 100644
--- a/compiler/testData/codegen/box/inference/ifWithAssignmentAndNothingBranch.kt
+++ b/compiler/testData/codegen/box/inference/ifWithAssignmentAndNothingBranch.kt
@@ -1,4 +1,3 @@
-// IGNORE_BACKEND_K2: ANY
 // ISSUE: KT-78127
 
 fun <T : Any> materialize(): T {
@@ -7,8 +6,6 @@
 
 var b = true
 
-var s: Nothing? = null
-
 fun box(): String {
     var x: String? = null
 
diff --git a/compiler/testData/codegen/box/inference/tryCatchAtAssignment.kt b/compiler/testData/codegen/box/inference/tryCatchAtAssignment.kt
index 5420a45..b4caa9d 100644
--- a/compiler/testData/codegen/box/inference/tryCatchAtAssignment.kt
+++ b/compiler/testData/codegen/box/inference/tryCatchAtAssignment.kt
@@ -1,4 +1,3 @@
-// IGNORE_BACKEND_K2: ANY
 // ISSUE: KT-77008
 
 interface I {
diff --git a/compiler/testData/codegen/box/inference/whenAtAssignment.kt b/compiler/testData/codegen/box/inference/whenAtAssignment.kt
index 3a77239..e1df20ab 100644
--- a/compiler/testData/codegen/box/inference/whenAtAssignment.kt
+++ b/compiler/testData/codegen/box/inference/whenAtAssignment.kt
@@ -1,4 +1,3 @@
-// IGNORE_BACKEND_K2: ANY
 // ISSUE: KT-77008
 
 interface I {