Skip to content

Commit de1247d

Browse files
authored
Fix unwrapping assignment expressions in match subject (#19742)
The `else_map` from guard clauses can only be applied properly if the subject expression itself can be put on the binder. Unwrap assignment expressions so we don't need to fall back to a dummy name and loose the guard clause inference.
1 parent dcb4d69 commit de1247d

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

mypy/checker.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5552,10 +5552,10 @@ def visit_continue_stmt(self, s: ContinueStmt) -> None:
55525552
return
55535553

55545554
def visit_match_stmt(self, s: MatchStmt) -> None:
5555-
named_subject = self._make_named_statement_for_match(s)
55565555
# In sync with similar actions elsewhere, narrow the target if
55575556
# we are matching an AssignmentExpr
55585557
unwrapped_subject = collapse_walrus(s.subject)
5558+
named_subject = self._make_named_statement_for_match(s, unwrapped_subject)
55595559
with self.binder.frame_context(can_skip=False, fall_through=0):
55605560
subject_type = get_proper_type(self.expr_checker.accept(s.subject))
55615561

@@ -5646,9 +5646,8 @@ def visit_match_stmt(self, s: MatchStmt) -> None:
56465646
with self.binder.frame_context(can_skip=False, fall_through=2):
56475647
pass
56485648

5649-
def _make_named_statement_for_match(self, s: MatchStmt) -> Expression:
5649+
def _make_named_statement_for_match(self, s: MatchStmt, subject: Expression) -> Expression:
56505650
"""Construct a fake NameExpr for inference if a match clause is complex."""
5651-
subject = s.subject
56525651
if self.binder.can_put_directly(subject):
56535652
# Already named - we should infer type of it as given
56545653
return subject

test-data/unit/check-python310.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,16 @@ match m:
13931393
reveal_type(a)
13941394
[builtins fixtures/isinstancelist.pyi]
13951395

1396+
[case testMatchSubjectAssignExprWithGuard]
1397+
from typing import Optional
1398+
def func() -> Optional[str]: ...
1399+
1400+
match m := func():
1401+
case _ if not m:
1402+
reveal_type(m) # N: Revealed type is "Union[Literal[''], None]"
1403+
case _:
1404+
reveal_type(m) # N: Revealed type is "builtins.str"
1405+
13961406
-- Exhaustiveness --
13971407

13981408
[case testMatchUnionNegativeNarrowing]

0 commit comments

Comments
 (0)