Closed
Description
Bug Report
Mypy sometimes loses track of the narrowed type of a variable, at least when the variable can be uninitialized in some code paths. This can happen when variables is both initialized and narrowed in a conditional block.
To Reproduce
if int():
x: int | str
x = 0
x = str(x)
reveal_type(x) # int | str
Expected Behavior
Revealed type is str
.
Actual Behavior
Revealed type is int | str
.
Discussion
Here are some more realistic examples:
def cond() -> bool:
return True
if cond():
x: int | str
x = 0
x = str(x)
if cond():
reveal_type(x) # int | str
for i in [1]:
y: int | bytes
y = 0
y = bytes(y)
reveal_type(y) # int | bytes
def f(x: int | None) -> int:
return x or 1
def g() -> None:
if cond():
if int():
z = None
else:
z = 1
z = f(z)
if cond():
reveal_type(z) # int | None
def h() -> None:
if cond():
if int():
z = 1
else:
z = None
z = f(z)
if cond():
reveal_type(z) # int | None
This issue interferes with inferring union types from assignments (#18568).
@ilevkivskyi Do you have an idea of how to fix this, since you did some work on the binder recently? If a variable hasn't been assigned in some conditional code path, maybe the type should be treated as Never
when merging types from different code paths?