Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd64d86

Browse files
committed
Fix two type inference bugs related to enum value attributes
A few bugs in type operations were exposed by #11962. This fixes them. Fix #12051, but other use cases are affected as well. First, when we erase last known values in an union with multiple Instance types, make sure that the resulting union doesn't have duplicate erased types. The duplicate items weren't incorrect as such, but they could cause overly complex error messages and potentially slow type checking performance. Second, make the join of a union type and Any commutative. Previously the result dependend on the order of the operands, which was clearly incorrect.
1 parent 0cec4f7 commit cd64d86

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

mypy/erasetype.py

+9
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,12 @@ def visit_type_alias_type(self, t: TypeAliasType) -> Type:
161161
# Type aliases can't contain literal values, because they are
162162
# always constructed as explicit types.
163163
return t
164+
165+
def visit_union_type(self, t: UnionType) -> Type:
166+
new = super().visit_union_type(t)
167+
new = get_proper_type(new)
168+
if isinstance(new, UnionType):
169+
from mypy.typeops import make_simplified_union
170+
# Erasure can result in many duplicate items; remove them.
171+
new = make_simplified_union(new.items)
172+
return new

mypy/join.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,15 @@ def join_types(s: Type, t: Type, instance_joiner: Optional[InstanceJoiner] = Non
175175
s = mypy.typeops.true_or_false(s)
176176
t = mypy.typeops.true_or_false(t)
177177

178+
if isinstance(s, UnionType) and not isinstance(t, UnionType):
179+
s, t = t, s
180+
178181
if isinstance(s, AnyType):
179182
return s
180183

181184
if isinstance(s, ErasedType):
182185
return t
183186

184-
if isinstance(s, UnionType) and not isinstance(t, UnionType):
185-
s, t = t, s
186-
187187
if isinstance(s, NoneType) and not isinstance(t, NoneType):
188188
s, t = t, s
189189

test-data/unit/check-enum.test

+18
Original file line numberDiff line numberDiff line change
@@ -1868,3 +1868,21 @@ class WithOverload(enum.IntEnum):
18681868
class SubWithOverload(WithOverload): # Should pass
18691869
pass
18701870
[builtins fixtures/tuple.pyi]
1871+
1872+
[case testEnumtValueUnionSimplification]
1873+
from enum import IntEnum
1874+
from typing import Any
1875+
1876+
class C(IntEnum):
1877+
X = 0
1878+
Y = 1
1879+
Z = 2
1880+
1881+
def f1(c: C) -> None:
1882+
x = {'x': c.value}
1883+
reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int]"
1884+
1885+
def f2(c: C, a: Any) -> None:
1886+
x = {'x': c.value, 'y': a}
1887+
reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, Any]"
1888+
[builtins fixtures/dict.pyi]

0 commit comments

Comments
 (0)