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?
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
Expected Behavior
Revealed type is
str.Actual Behavior
Revealed type is
int | str.Discussion
Here are some more realistic examples:
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
Neverwhen merging types from different code paths?