Narrowing enums causes `.value` to be typed as `Any`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
Apologies if this has already been reported, but I couldn't find an existing issue for it.
The issue I'm seeing is related to accessing the .value of an Enum after "narrowing" it with the is operator. It seems like the narrowing (to Union[Literal[...]]) works as expected, but then it fails to realize that the .value of all the variants have the same type (and so falls back to Any).
This only affects runs with --warn-return-any enabled:
$ mypy --config-file /dev/null --warn-return-any enum_narrowing.py
To Reproduce
It's probably easiest to see in this example:
import enum
from typing import Tuple
RGB = Tuple[int, int, int]
class Color(enum.Enum):
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
def red(self) -> int:
if self is Color.WHITE:
return 255
return self.value[0] # error: Returning Any from function declared to return "int"
(playground URL: https://mypy-play.net/?mypy=latest&python=3.8&flags=warn-return-any&gist=b2a6df92fb37717e5c9d7542b6e88fec)
Expected Behavior
This should deduce that self.value has type RGB and succeed.
Actual Behavior
If I add some reveal_type(self) and reveal_type(self.value)s before/after the narrowing, I get this output:
enum_narrowing.py:11: note: Revealed type is "enum_narrowing.Color"
enum_narrowing.py:12: note: Revealed type is "Tuple[Literal[255]?, Literal[255]?, Literal[255]?]"
enum_narrowing.py:15: note: Revealed type is "Literal[enum_narrowing.Color.BLACK]"
enum_narrowing.py:16: note: Revealed type is "Any"
Your Environment
$ python --version
Python 3.8.0
$ mypy --version
mypy 0.991 (compiled: yes)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the provided mypy command against enum_narrowing.py and compare the revealed types before and after the is narrowing. Trace the enum-member narrowing and .value type handling; the fix is complete when self.value[0] is inferred as an int and the example passes with --warn-return-any.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100