From 7adb2358e5e5899b13afb041825370374fb97301 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 2 Mar 2026 22:46:16 -0500 Subject: [PATCH] [ty] Apply narrowing to walrus values --- .../resources/mdtest/narrow/truthiness.md | 12 ++++++++++++ crates/ty_python_semantic/src/types/narrow.rs | 19 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/narrow/truthiness.md b/crates/ty_python_semantic/resources/mdtest/narrow/truthiness.md index 5d52cb47daae4..e6ab0527cb778 100644 --- a/crates/ty_python_semantic/resources/mdtest/narrow/truthiness.md +++ b/crates/ty_python_semantic/resources/mdtest/narrow/truthiness.md @@ -364,6 +364,18 @@ def f(): reveal_type(x) # revealed: (str & ~AlwaysTruthy) | None ``` +## Narrowing the value of a named expression + +The value expression on the right-hand side of the walrus operator should also be narrowed: + +```py +def foo(value: int | None): + if foo := value: + reveal_type(value) # revealed: int & ~AlwaysFalsy + else: + reveal_type(value) # revealed: (int & ~AlwaysTruthy) | None +``` + ## Narrowing a union of a `TypedDict` and `None` ```py diff --git a/crates/ty_python_semantic/src/types/narrow.rs b/crates/ty_python_semantic/src/types/narrow.rs index c5d67c13254c9..0163be2b1383e 100644 --- a/crates/ty_python_semantic/src/types/narrow.rs +++ b/crates/ty_python_semantic/src/types/narrow.rs @@ -831,7 +831,16 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> { expr_named: &ast::ExprNamed, is_positive: bool, ) -> Option> { - self.evaluate_simple_expr(&expr_named.target, is_positive) + let target_constraints = self.evaluate_simple_expr(&expr_named.target, is_positive); + let value_constraints = self.evaluate_simple_expr(&expr_named.value, is_positive); + match (target_constraints, value_constraints) { + (Some(mut target), Some(value)) => { + merge_constraints_and(&mut target, value); + Some(target) + } + (Some(constraints), None) | (None, Some(constraints)) => Some(constraints), + (None, None) => None, + } } fn evaluate_expr_eq(&mut self, lhs_ty: Type<'db>, rhs_ty: Type<'db>) -> Option> { @@ -2177,8 +2186,12 @@ impl<'db, 'a> PossiblyNarrowedPlacesBuilder<'db, 'a> { } // Boolean operations combine places from all sub-expressions ast::Expr::BoolOp(bool_op) => self.expr_bool_op(bool_op), - // Named expressions narrow the target - ast::Expr::Named(expr_named) => self.simple_expr(&expr_named.target), + // Named expressions narrow both the target and the value + ast::Expr::Named(expr_named) => { + let mut places = self.simple_expr(&expr_named.target); + places.extend(self.expression_node(&expr_named.value)); + places + } _ => PossiblyNarrowedPlaces::default(), } }