Skip to content

Commit

Permalink
Narrow types for walrus assignment in if statements (#8258)
Browse files Browse the repository at this point in the history
Fixes #7313
Fixes #7316
  • Loading branch information
hauntsaninja authored and msullivan committed Jan 8, 2020
1 parent 7055725 commit 33fc8a3
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 9 deletions.
2 changes: 2 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3982,6 +3982,8 @@ def has_no_custom_eq_checks(t: Type) -> bool:
partial_type_maps.append((if_map, else_map))

return reduce_conditional_maps(partial_type_maps)
elif isinstance(node, AssignmentExpr):
return self.find_isinstance_check_helper(node.target)
elif isinstance(node, RefExpr):
# Restrict the type of the variable to True-ish/False-ish in the if and else branches
# respectively
Expand Down
1 change: 1 addition & 0 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2773,6 +2773,7 @@ def visit_assignment_expr(self, e: AssignmentExpr) -> Type:
value = self.accept(e.value)
self.chk.check_assignment(e.target, e.value)
self.chk.check_final(e)
self.find_partial_type_ref_fast_path(e.target)
return value

def visit_unary_expr(self, e: UnaryExpr) -> Type:
Expand Down
27 changes: 18 additions & 9 deletions test-data/unit/check-python38.test
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,7 @@ def check_binder(x: Optional[int], y: Optional[int], z: Optional[int], a: Option
reveal_type(y) # N: Revealed type is 'Union[builtins.int, None]'

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

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

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

def check_narrow(x: Optional[int]) -> None:
if (y := x):
reveal_type(y) # N: Revealed type is 'builtins.int'
[builtins fixtures/f_string.pyi]

[case testWalrusPartialTypes]
from typing import List

def check_partial_list() -> None:
if (x := []):
x.append(3)
if (x := []): # E: Need type annotation for 'x' (hint: "x: List[<type>] = ...")
pass

reveal_type(x) # N: Revealed type is 'builtins.list[builtins.int]'
y: List[str]
if (y := []):
pass

[builtins fixtures/f_string.pyi]
if (z := []):
z.append(3)
reveal_type(z) # N: Revealed type is 'builtins.list[builtins.int]'
[builtins fixtures/list.pyi]

0 comments on commit 33fc8a3

Please sign in to comment.