Skip to content

Commit e03fe98

Browse files
committed
Speed up make_simplified_union for Literal[string]s (issue python#9169)
1 parent 4cf246f commit e03fe98

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

Diff for: mypy/typeops.py

+27-15
Original file line numberDiff line numberDiff line change
@@ -344,21 +344,33 @@ def make_simplified_union(items: Sequence[Type],
344344
from mypy.subtypes import is_proper_subtype
345345

346346
removed = set() # type: Set[int]
347-
for i, ti in enumerate(items):
348-
if i in removed: continue
349-
# Keep track of the truishness info for deleted subtypes which can be relevant
350-
cbt = cbf = False
351-
for j, tj in enumerate(items):
352-
if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased):
353-
# We found a redundant item in the union.
354-
removed.add(j)
355-
cbt = cbt or tj.can_be_true
356-
cbf = cbf or tj.can_be_false
357-
# if deleted subtypes had more general truthiness, use that
358-
if not ti.can_be_true and cbt:
359-
items[i] = true_or_false(ti)
360-
elif not ti.can_be_false and cbf:
361-
items[i] = true_or_false(ti)
347+
348+
# Avoid slow nested for loop for Union of Literal of strings (issue #9169)
349+
if all((isinstance(item, LiteralType) and
350+
item.fallback.type.fullname == 'builtins.str')
351+
for item in items):
352+
seen = set() # type: Set[str]
353+
for index, item in enumerate(items):
354+
if item.value in seen:
355+
removed.add(index)
356+
seen.add(item.value)
357+
358+
else:
359+
for i, ti in enumerate(items):
360+
if i in removed: continue
361+
# Keep track of the truishness info for deleted subtypes which can be relevant
362+
cbt = cbf = False
363+
for j, tj in enumerate(items):
364+
if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased):
365+
# We found a redundant item in the union.
366+
removed.add(j)
367+
cbt = cbt or tj.can_be_true
368+
cbf = cbf or tj.can_be_false
369+
# if deleted subtypes had more general truthiness, use that
370+
if not ti.can_be_true and cbt:
371+
items[i] = true_or_false(ti)
372+
elif not ti.can_be_false and cbf:
373+
items[i] = true_or_false(ti)
362374

363375
simplified_set = [items[i] for i in range(len(items)) if i not in removed]
364376
return UnionType.make_union(simplified_set, line, column)

0 commit comments

Comments
 (0)