Skip to content

Binder loses narrowed type of a variable if variable may be uninitialized #18619

Closed
@JukkaL

Description

@JukkaL

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?

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions