Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__eq__ methods disable narrowing in the else block #17229

Open
DetachHead opened this issue May 9, 2024 · 0 comments
Open

__eq__ methods disable narrowing in the else block #17229

DetachHead opened this issue May 9, 2024 · 0 comments
Labels
bug mypy got something wrong

Comments

@DetachHead
Copy link
Contributor

from typing import Literal, override


class Foo:
    @override
    def __eq__(self, value: object, /) -> bool:
        return True


def fun(a: Foo | Literal["a"]) -> None:
    if a == "a":
        reveal_type(a) # Foo | Literal['a']
    else:
        reveal_type(a) # Foo | Literal['a']

playground

in this case, it's safe to narrow to Foo in the else block, because the Literal["a"] cannot have a custom __eq__. this means if a == "a" returns False, there's no chance that a is a Literal["a"], but if it returns True then it's still possible for it to be a Foo because of the Foo.__eq__.

therefore, the narrowing should work like this:

def fun(a: Foo | Literal["a"]) -> None:
    if a == "a":
        reveal_type(a) # Foo | Literal['a']
    else:
        reveal_type(a) # Foo

this would also be consistent with pyright's behavior: playground

@DetachHead DetachHead added the bug mypy got something wrong label May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

1 participant