Skip to content

Truthyness inference incorrect for some Enum types #17333

Closed
@Daverball

Description

@Daverball

Bug Report

It looks like the enum plugin incorrectly assumes that __bool__ on enum literals will always return Literal[True], while this is the default behavior, it is not correct when someone explicitly overrides __bool__. Moreover this special casing is only applied to enum literals, but not the base enum type, which should behave the same as individual members.

To Reproduce

https://mypy-play.net/?mypy=master&python=3.12&gist=dc60c5c82ba6589e5f1d03654439b05e

import enum
from typing import Any, Literal

class Foo(enum.Enum):
    X = 0

class Bar(enum.Enum):
    X = 0
    
    def __bool__(self) -> Literal[False]:
        return False

def a(x: Any | Literal[Foo.X]):
    reveal_type(x)
    if x:
        reveal_type(x)
    else:
        reveal_type(x)

def b(x: Any | Foo):
    reveal_type(x)
    if x:
        reveal_type(x)
    else:
        reveal_type(x)  # wrong, doesn't match literal behavior

def c(x: Any | Literal[Bar.X]):
    reveal_type(x)
    if x:
        reveal_type(x)  # wrong, it's backwards
    else:
        reveal_type(x)  # wrong, it's backwards

def d(x: Any | Bar):
    reveal_type(x)
    if x:
        reveal_type(x)
    else:
        reveal_type(x)

Your Environment

  • Mypy version used: Playground with master branch
  • Mypy command-line flags: Default
  • Mypy configuration options from mypy.ini (and other config files): Default
  • Python version used: 3.12

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions