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?