Skip to content

Commit 745d300

Browse files
JelleZijlstrailevkivskyi
authored andcommitted
disallow generic Enums and fix assigning Enum indexes (#3140)
* disallow generic Enums and fix assigning Enum indexes Fixes #3137 * add "x = E[1]" test
1 parent f3fb6b4 commit 745d300

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

mypy/semanal.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,8 @@ def analyze_base_classes(self, defn: ClassDef) -> None:
10751075
# the MRO. Fix MRO if needed.
10761076
if info.mro and info.mro[-1].fullname() != 'builtins.object':
10771077
info.mro.append(self.object_type().type)
1078+
if defn.info.is_enum and defn.type_vars:
1079+
self.fail("Enum class cannot be generic", defn)
10781080

10791081
def expr_to_analyzed_type(self, expr: Expression) -> Type:
10801082
if isinstance(expr, CallExpr):

mypy/typeanal.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ def analyze_type_alias(node: Expression,
6161
base.fullname in type_constructors or
6262
base.kind == TYPE_ALIAS):
6363
return None
64+
# Enums can't be generic, and without this check we may incorrectly interpret indexing
65+
# an Enum class as creating a type alias.
66+
if isinstance(base.node, TypeInfo) and base.node.is_enum:
67+
return None
6468
else:
6569
return None
6670
else:

test-data/unit/check-enum.test

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,37 @@ main:5: error: Revealed type is '__main__.E'
150150
from enum import IntEnum
151151
class E(IntEnum):
152152
a = 1
153-
E[1]
154-
[out]
155-
main:4: error: Enum index should be a string (actual index type "int")
153+
E[1] # E: Enum index should be a string (actual index type "int")
154+
x = E[1] # E: Enum index should be a string (actual index type "int")
155+
156+
[case testEnumIndexIsNotAnAlias]
157+
from enum import Enum
158+
159+
class E(Enum):
160+
a = 1
161+
b = 2
162+
reveal_type(E['a']) # E: Revealed type is '__main__.E'
163+
E['a']
164+
x = E['a']
165+
reveal_type(x) # E: Revealed type is '__main__.E'
166+
167+
def get_member(name: str) -> E:
168+
val = E[name]
169+
return val
170+
171+
reveal_type(get_member('a')) # E: Revealed type is '__main__.E'
172+
173+
[case testGenericEnum]
174+
from enum import Enum
175+
from typing import Generic, TypeVar
176+
177+
T = TypeVar('T')
178+
179+
class F(Generic[T], Enum): # E: Enum class cannot be generic
180+
x: T
181+
y: T
182+
183+
reveal_type(F[int].x) # E: Revealed type is '__main__.F[builtins.int*]'
156184

157185
[case testEnumFlag]
158186
from enum import Flag

0 commit comments

Comments
 (0)