mypy icon indicating copy to clipboard operation
mypy copied to clipboard

False-positive "Non-overlapping equality check" comparing `Enum`s `self` to members

Open bersbersbers opened this issue 1 year ago • 1 comments

Bug Report

mypy does not understand that in an Enum, self can be compared to its members.

To Reproduce

from enum import Enum, auto

class Glass(Enum):
    HALF_FULL = auto()
    HALF_EMPTY = auto()

    def print(self) -> str:
        if self == self.HALF_FULL:
            print("half full")
            return

        raise ValueError("Glass is not half-full.")

# prints "half full"
Glass.HALF_FULL.print()

https://mypy-play.net/?mypy=latest&python=3.12&flags=strict&gist=edf65b45f562ed246f05592cc02f1fda

Expected Behavior

No error.

Actual Behavior

main.py:9: error: Non-overlapping equality check (left operand type: "Glass", right operand type: "auto")  [comparison-overlap]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.10.0
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.12.3

https://github.com/python/mypy/issues/16327 seems related.

bersbersbers avatar Jun 03 '24 09:06 bersbersbers

I would like to add an issue I encountered that appears related to this issue. Mypy creates a similar false positive "non-overlapping equality check" when an Enum that is a field of a class is modified by some method that is run on that class. I've added a minimal example below:

To Reproduce:

from enum import Enum


class SWITCH(Enum):
    ON = 1
    OFF = 0


class SwitchFlipper:
    def __init__(self, enum_value: SWITCH):
        self.enum_value = enum_value

    def flip_switch(self) -> None:
        if self.enum_value == SWITCH.ON:
            self.enum_value = SWITCH.OFF
        else:
            self.enum_value = SWITCH.ON


flipper = SwitchFlipper(SWITCH.OFF)
assert flipper.enum_value == SWITCH.OFF
flipper.flip_switch()
assert flipper.enum_value == SWITCH.ON

Expected Behavior

No error.

Actual Behavior

error: Non-overlapping equality check (left operand type: "Literal[SWITCH.OFF]", right operand type: "Literal[Switch.ON]") [comparison-overlap]

My Environment:

Mypy version used: >=1.4.0 (issue does not show up in version 1.3.0 or earlier)
Mypy command-line flags: --strict
Mypy configuration options from mypy.ini (and other config files): none
Python version used: 3.8.10

TomHKeysight avatar Aug 27 '24 15:08 TomHKeysight

Minimal Reproducible Example

from enum import Enum

class State(Enum):
    IDLE = 0
    RUNNING = 1

class Worker:
    def __init__(self: "Worker") -> None:
        self.state = State.IDLE

    def run(self: "Worker") -> None:
        self.state = State.RUNNING

class TestWorker:
    def test_state(self: "TestWorker") -> None:
        worker = Worker()
        assert worker.state == State.IDLE
        worker.run()
        assert worker.state == State.RUNNING

Expected Behaviour

$ mypy mre.py --strict
Success: no issues found in 1 source file

Actual Behaviour

$ mypy mre.py --strict
mre.py:19: error: Non-overlapping equality check (left operand type: "Literal[State.IDLE]", right operand type: "Literal[State.RUNNING]")  [comparison-overlap]
Found 1 error in 1 file (checked 1 source file)

Environment

$ mypy --version
mypy 1.11.2 (compiled: yes)

arthurazs avatar Sep 11 '24 14:09 arthurazs

+1

hanna-becker avatar Sep 30 '24 15:09 hanna-becker

Same for me

class TochkaDocumentType:
    BENEFICIARY = 'beneficiary'
    DEAL = 'deal'


@dataclass
class TochkaUploadDocumentEntity:
    doc_type: TochkaDocumentType
    beneficiary_id: str
    deal_id: str | None


  upload_message: TochkaUploadDocumentEntity = message
  if upload_message.doc_type == TochkaDocumentType.DEAL:

The error:

error: Non-overlapping equality check (left operand type: "TochkaDocumentType", right operand type: "str")  [comparison-overlap]

Mypy version

mypy 1.13.0 (compiled: yes)

verhovensky avatar Nov 06 '24 09:11 verhovensky

@verhovensky I think your issue there is that your TochkaDocumentType does not extend Enum, so mypy is correct in observing that you are comparing an object of type TochkaDocumentType to a field of type str.

TomHKeysight avatar Nov 06 '24 09:11 TomHKeysight

@TomHKeysight You are right, my bad After inheriting from StrEnum - the error is gone

verhovensky avatar Nov 06 '24 10:11 verhovensky

Please note that the narrowing issue reported by @TomHKeysight and @arthurazs is completely irrelevant to the OP and is tracked in #17537. This ticket itself is a duplicate of #10910 modulo is vs ==.

sterliakov avatar Jul 11 '25 00:07 sterliakov