Skip to content

Commit 33fc8a3

Browse files
hauntsaninjamsullivan
authored andcommitted
Narrow types for walrus assignment in if statements (#8258)
Fixes #7313 Fixes #7316
1 parent 7055725 commit 33fc8a3

File tree

3 files changed

+21
-9
lines changed

3 files changed

+21
-9
lines changed

mypy/checker.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3982,6 +3982,8 @@ def has_no_custom_eq_checks(t: Type) -> bool:
39823982
partial_type_maps.append((if_map, else_map))
39833983

39843984
return reduce_conditional_maps(partial_type_maps)
3985+
elif isinstance(node, AssignmentExpr):
3986+
return self.find_isinstance_check_helper(node.target)
39853987
elif isinstance(node, RefExpr):
39863988
# Restrict the type of the variable to True-ish/False-ish in the if and else branches
39873989
# respectively

mypy/checkexpr.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,6 +2773,7 @@ def visit_assignment_expr(self, e: AssignmentExpr) -> Type:
27732773
value = self.accept(e.value)
27742774
self.chk.check_assignment(e.target, e.value)
27752775
self.chk.check_final(e)
2776+
self.find_partial_type_ref_fast_path(e.target)
27762777
return value
27772778

27782779
def visit_unary_expr(self, e: UnaryExpr) -> Type:

test-data/unit/check-python38.test

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,7 @@ def check_binder(x: Optional[int], y: Optional[int], z: Optional[int], a: Option
266266
reveal_type(y) # N: Revealed type is 'Union[builtins.int, None]'
267267

268268
if x and (y := 1):
269-
# TODO should just be int
270-
# This is because in check_boolean_op in checkexpr.py we accept the right conditional
271-
# within a binder frame context, so the types assigned in it are lost later. Perhaps
272-
# we need to make find_isinstance_check() walrus-aware.
273-
reveal_type(y) # N: Revealed type is 'Union[builtins.int, None]'
269+
reveal_type(y) # N: Revealed type is 'builtins.int'
274270

275271
if (a := 1) and x:
276272
reveal_type(a) # N: Revealed type is 'builtins.int'
@@ -288,10 +284,23 @@ def check_partial() -> None:
288284

289285
reveal_type(x) # N: Revealed type is 'Union[builtins.int, None]'
290286

287+
def check_narrow(x: Optional[int]) -> None:
288+
if (y := x):
289+
reveal_type(y) # N: Revealed type is 'builtins.int'
290+
[builtins fixtures/f_string.pyi]
291+
292+
[case testWalrusPartialTypes]
293+
from typing import List
294+
291295
def check_partial_list() -> None:
292-
if (x := []):
293-
x.append(3)
296+
if (x := []): # E: Need type annotation for 'x' (hint: "x: List[<type>] = ...")
297+
pass
294298

295-
reveal_type(x) # N: Revealed type is 'builtins.list[builtins.int]'
299+
y: List[str]
300+
if (y := []):
301+
pass
296302

297-
[builtins fixtures/f_string.pyi]
303+
if (z := []):
304+
z.append(3)
305+
reveal_type(z) # N: Revealed type is 'builtins.list[builtins.int]'
306+
[builtins fixtures/list.pyi]

0 commit comments

Comments
 (0)