Binder loses narrowed type of a variable if variable may be uninitialized
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?