Skip to content

Commit a8bb470

Browse files
committed
fix zip
1 parent 5a6464a commit a8bb470

3 files changed

Lines changed: 46 additions & 35 deletions

File tree

mypy/checkpattern.py

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import itertools
56
from collections import defaultdict
67
from typing import Final, NamedTuple
78

@@ -242,79 +243,92 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType:
242243
if star_position is not None:
243244
required_patterns -= 1
244245

245-
#
246-
# get inner types of original type
247-
# 1. Go through all possible types and filter to only those which are sequences that could match that number of items
248-
# 2. If there is exactly one tuple left with an unpack, then use that type and the unpack index
249-
# 3. Otherwise, take the product of the item types so that each index can have a unique type. For tuples with unpack
250-
# fallback to merging all of their types for each index since we can't handle multiple unpacked items at once yet.
246+
# 1. Go through all possible types and filter to only those which are sequences that
247+
# could match that number of items
248+
# 2. If there is exactly one tuple left with an unpack, then use that type
249+
# and the unpack index
250+
# 3. Otherwise, take the product of the item types so that each index can have a
251+
# unique type. For tuples with unpack fallback to merging all of their types
252+
# for each index, since we can't handle multiple unpacked items at once yet.
251253

252254
# Whether we have encountered a type that we don't know how to handle in the union
253255
unknown_type = False
254256
# A list of types that could match any of the items in the sequence.
255257
sequence_types: list[Type] = []
256258
# A list of tuple types that could match the sequence, per index
257259
tuple_types: list[list[Type]] = []
258-
# A list of all the unpack tuple types that we encountered, each containing the tuple type, unpack index, and union index
260+
# A list of all the unpack tuple types that we encountered, each containing the
261+
# tuple type, unpack index, and union index
259262
unpack_tuple_types: list[tuple[TupleType, int, int]] = []
260263
for i, t in enumerate(
261264
current_type.items if isinstance(current_type, UnionType) else [current_type]
262265
):
263266
t = get_proper_type(t)
264267
if isinstance(t, TupleType):
265-
t_items = list(t.items)
266-
unpack_index = find_unpack_in_list(t_items)
268+
tuple_items = list(t.items)
269+
unpack_index = find_unpack_in_list(tuple_items)
267270
if unpack_index is None:
268-
size_diff = len(t_items) - required_patterns
271+
size_diff = len(tuple_items) - required_patterns
269272
if size_diff < 0:
270273
continue
271-
elif size_diff > 0 and star_position is None:
274+
if size_diff > 0 and star_position is None:
272275
continue
273-
elif not size_diff and star_position is not None:
274-
t_items.append(UninhabitedType())
275-
tuple_types.append(t_items)
276+
if not size_diff and star_position is not None:
277+
# Above we subtract from required_patterns if star_position is not None
278+
tuple_items.append(UninhabitedType())
279+
tuple_types.append(tuple_items)
276280
else:
277281
normalized_inner_types = []
278-
for it in t_items:
282+
for it in tuple_items:
279283
# Unfortunately, it is not possible to "split" the TypeVarTuple
280284
# into individual items, so we just use its upper bound for the whole
281285
# analysis instead.
282286
if isinstance(it, UnpackType) and isinstance(it.type, TypeVarTupleType):
283287
it = UnpackType(it.type.upper_bound)
284288
normalized_inner_types.append(it)
285-
t_items = normalized_inner_types
286-
t = t.copy_modified(items=normalized_inner_types)
287-
if len(t_items) - 1 > required_patterns and star_position is None:
289+
if (
290+
len(normalized_inner_types) - 1 > required_patterns
291+
and star_position is None
292+
):
288293
continue
294+
t = t.copy_modified(items=normalized_inner_types)
289295
unpack_tuple_types.append((t, unpack_index, i))
290-
# add the combined tuple type to the sequence types in case we have multiple unpacks we want to combine them all
296+
# In case we have multiple unpacks we want to combine them all, so add
297+
# the combined tuple type to the sequence types.
291298
sequence_types.append(self.chk.iterable_item_type(tuple_fallback(t), o))
292299
elif isinstance(t, AnyType):
293300
sequence_types.append(AnyType(TypeOfAny.from_another_any, t))
294301
elif self.chk.type_is_iterable(t) and isinstance(t, Instance):
295302
sequence_types.append(self.chk.iterable_item_type(t, o))
296303
else:
297304
unknown_type = True
298-
# if we only got one unpack tuple type, we can use that
305+
306+
inner_types: list[Type]
307+
308+
# If we only got one unpack tuple type, we can use that
299309
unpack_index = None
300310
if len(unpack_tuple_types) == 1 and len(sequence_types) == 1 and not tuple_types:
301311
update_tuple_type, unpack_index, union_index = unpack_tuple_types[0]
302-
inner_types: list[Type] = update_tuple_type.items
312+
inner_types = update_tuple_type.items
303313
if isinstance(current_type, UnionType):
304314
union_items = list(current_type.items)
305315
union_items[union_index] = update_tuple_type
306-
current_type = current_type.copy_modified(items=union_items)
316+
current_type = UnionType.make_union(items=union_items)
307317
else:
308318
current_type = update_tuple_type
309-
# if we only got tuples we can't match, then exit early
319+
# If we only got tuples we can't match, then exit early
310320
elif not tuple_types and not sequence_types and not unknown_type:
311321
return self.early_non_match()
312322
elif tuple_types:
323+
inner_types = [
324+
make_simplified_union([*sequence_types, *[t for t in group if t is not None]])
325+
for group in itertools.zip_longest(*tuple_types)
326+
]
313327
inner_types = [make_simplified_union([*sequence_types, *x]) for x in zip(*tuple_types)]
328+
elif sequence_types:
329+
inner_types = [make_simplified_union(sequence_types)] * len(o.patterns)
314330
else:
315-
object_type = self.chk.named_type("builtins.object")
316-
unioned = make_simplified_union(sequence_types) if sequence_types else object_type
317-
inner_types = [unioned] * len(o.patterns)
331+
inner_types = [self.chk.named_type("builtins.object")] * len(o.patterns)
318332

319333
#
320334
# match inner patterns

mypy/types.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2918,15 +2918,6 @@ def __init__(
29182918
self.original_str_expr: str | None = None
29192919
self.original_str_fallback: str | None = None
29202920

2921-
def copy_modified(self, *, items: Sequence[Type]) -> UnionType:
2922-
return UnionType(
2923-
items,
2924-
line=self.line,
2925-
column=self.column,
2926-
is_evaluated=self.is_evaluated,
2927-
uses_pep604_syntax=self.uses_pep604_syntax,
2928-
)
2929-
29302921
def can_be_true_default(self) -> bool:
29312922
return any(item.can_be_true for item in self.items)
29322923

test-data/unit/check-python310.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,12 @@ match m8:
16171617
reveal_type(b8) # N: Revealed type is "Union[builtins.float, builtins.str]"
16181618
reveal_type(rest8) # N: Revealed type is "builtins.list[builtins.float]"
16191619

1620+
m9: tuple[str, str, int] | tuple[str, str]
1621+
match m9:
1622+
case (a9, *rest9):
1623+
reveal_type(a9) # N: Revealed type is "builtins.str"
1624+
reveal_type(rest9) # N: Revealed type is "builtins.list[builtins.str]"
1625+
16201626
[builtins fixtures/tuple.pyi]
16211627

16221628

0 commit comments

Comments
 (0)