mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Generic type incorrectly un-narrowed following TypeIs

Open hauntsaninja opened this issue 6 months ago • 3 comments

from typing_extensions import Any, TypeIs, reveal_type

class C[T]:
    v: T

def is_int(v: object) -> TypeIs[C[int]]: ...

def f(c: C[Any]):
    if is_int(c):
        reveal_type(c)
    reveal_type(c)  # should be C[Any], but is C[int]

hauntsaninja avatar Jun 12 '25 04:06 hauntsaninja

Even worse,

from typing_extensions import Any, TypeIs, reveal_type

class C[T]:
    v: T

def is_int(v: object) -> TypeIs[C[int]]: ...

def f(c: C[Any]) -> None:
    if is_int(c):
        reveal_type(c)  # N: Revealed type is "__main__.C[builtins.int]"
    else:
        reveal_type(c)  # E: Statement is unreachable  [unreachable]
    reveal_type(c)  # N: Revealed type is "__main__.C[builtins.int]"

C[Any] can definitely be some C that is not C[int]! These two problems have the same cause - "implicit" else was unreachable, so the binder narrowed c to union of reachable branches.

sterliakov avatar Jun 12 '25 11:06 sterliakov

Is this the same as #18009?

brianschubert avatar Jun 12 '25 12:06 brianschubert

It seems #18193 fixes this, I'll see about picking that back up

from typing_extensions import Any, TypeIs, reveal_type

class C[T]:
    v: T

def is_int(v: object) -> TypeIs[C[int]]: ...

def f(c: C[Any]) -> None:
    if is_int(c):
        reveal_type(c)  # N: Revealed type is "__main__.C[builtins.int]"
    else:
        reveal_type(c)  # N: Revealed type is "__main__.C[Any]"
    reveal_type(c)  # N: Revealed type is "__main__.C[Any]"

brianschubert avatar Jun 12 '25 12:06 brianschubert