From e03fe98801671d60b5f87e76a9379b2c14ef3387 Mon Sep 17 00:00:00 2001 From: Akuli Date: Wed, 22 Jul 2020 21:41:02 +0300 Subject: [PATCH 1/4] Speed up make_simplified_union for Literal[string]s (issue #9169) --- mypy/typeops.py | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/mypy/typeops.py b/mypy/typeops.py index 0833b15a0bee..f238e97e278d 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -344,21 +344,33 @@ def make_simplified_union(items: Sequence[Type], from mypy.subtypes import is_proper_subtype removed = set() # type: Set[int] - for i, ti in enumerate(items): - if i in removed: continue - # Keep track of the truishness info for deleted subtypes which can be relevant - cbt = cbf = False - for j, tj in enumerate(items): - if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased): - # We found a redundant item in the union. - removed.add(j) - cbt = cbt or tj.can_be_true - cbf = cbf or tj.can_be_false - # if deleted subtypes had more general truthiness, use that - if not ti.can_be_true and cbt: - items[i] = true_or_false(ti) - elif not ti.can_be_false and cbf: - items[i] = true_or_false(ti) + + # Avoid slow nested for loop for Union of Literal of strings (issue #9169) + if all((isinstance(item, LiteralType) and + item.fallback.type.fullname == 'builtins.str') + for item in items): + seen = set() # type: Set[str] + for index, item in enumerate(items): + if item.value in seen: + removed.add(index) + seen.add(item.value) + + else: + for i, ti in enumerate(items): + if i in removed: continue + # Keep track of the truishness info for deleted subtypes which can be relevant + cbt = cbf = False + for j, tj in enumerate(items): + if i != j and is_proper_subtype(tj, ti, keep_erased_types=keep_erased): + # We found a redundant item in the union. + removed.add(j) + cbt = cbt or tj.can_be_true + cbf = cbf or tj.can_be_false + # if deleted subtypes had more general truthiness, use that + if not ti.can_be_true and cbt: + items[i] = true_or_false(ti) + elif not ti.can_be_false and cbf: + items[i] = true_or_false(ti) simplified_set = [items[i] for i in range(len(items)) if i not in removed] return UnionType.make_union(simplified_set, line, column) From 0c64e0fcfeaf91d19cda599ffd12b9230a9381cb Mon Sep 17 00:00:00 2001 From: Akuli Date: Wed, 22 Jul 2020 23:01:00 +0300 Subject: [PATCH 2/4] add missing cast --- mypy/typeops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/typeops.py b/mypy/typeops.py index f238e97e278d..3c3e07fcdbbb 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -350,7 +350,7 @@ def make_simplified_union(items: Sequence[Type], item.fallback.type.fullname == 'builtins.str') for item in items): seen = set() # type: Set[str] - for index, item in enumerate(items): + for index, item in enumerate(cast(Iterable[LiteralType], items)): if item.value in seen: removed.add(index) seen.add(item.value) From 29a71d8352249e6a84ae91c0ebc4c24b2cbb5dba Mon Sep 17 00:00:00 2001 From: Akuli Date: Thu, 23 Jul 2020 00:17:10 +0300 Subject: [PATCH 3/4] try to fix mypy self-check with asserts --- mypy/typeops.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/typeops.py b/mypy/typeops.py index 3c3e07fcdbbb..a31c07ae74a2 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -350,7 +350,9 @@ def make_simplified_union(items: Sequence[Type], item.fallback.type.fullname == 'builtins.str') for item in items): seen = set() # type: Set[str] - for index, item in enumerate(cast(Iterable[LiteralType], items)): + for index, item in enumerate(items): + assert isinstance(item, LiteralType) + assert isinstance(item.value, str) if item.value in seen: removed.add(index) seen.add(item.value) From f5490d970d3dfc0461d5107aed4ec7e497d8875f Mon Sep 17 00:00:00 2001 From: Akuli Date: Thu, 23 Jul 2020 22:13:04 +0300 Subject: [PATCH 4/4] try to trigger travis build to make it show correct status on github