Skip to content

TypeGuard/TypeIs broken on __call__ with fresh class #19575

@saulshanabrook

Description

@saulshanabrook

Bug Report

Using TypeGuard or TypeIs on the __call__ method on an object that is created in the if statement is broken.

To Reproduce

from typing import TypeGuard

class E:
    def __init__(self) -> None: ...
    def __call__(self, o: object) -> TypeGuard[int]:
        return True

x = object()

if E()(x):
    reveal_type(x)

or

from typing_extensions import TypeIs

class E:
    def __init__(self) -> None: ...
    def __call__(self, o: object) -> TypeIs[int]:
        return True

x = object()

if E()(x):
    reveal_type(x)

Expected Behavior

This should return:

main.py:11: note: Revealed type is "builtins.int"

Actual Behavior

Actually returns

main.py:11: note: Revealed type is "builtins.object"

Working Versions

Note that if you define the object first it acts correctly:

y = object()
o = E()
if o(y):
    reveal_type(y)
main.py:16: note: Revealed type is "builtins.int"

Or if it is a different method, it also works correctly:

from typing import TypeGuard

class E:
    def __init__(self) -> None: ...
    def m(self, o: object) -> TypeGuard[int]:
        return True

x = object()

if E().m(x):
    reveal_type(x)
main.py:11: note: Revealed type is "builtins.int"

Your Environment

Mypy playground 1.17.0 on Python 3.12

EDIT: made examples smaller by removing generics

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-narrowingConditional type narrowing / bindertopic-typeguard-typeisTypeGuard / TypeIs / PEP 647 / PEP 742

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions