MCPcopy Index your code
hub / github.com/python/mypy / join_tuples

Method join_tuples

mypy/join.py:470–575  ·  view source on GitHub ↗

Join two tuple types while handling variadic entries. This is surprisingly tricky, and we don't handle some tricky corner cases. Most of the trickiness comes from the variadic tuple items like *tuple[X, ...] since they can have arbitrary partial overlaps (while *Ts can't be

(self, s: TupleType, t: TupleType)

Source from the content-addressed store, hash-verified

468 return join_types(t.fallback, s)
469
470 def join_tuples(self, s: TupleType, t: TupleType) -> list[Type] | None:
471 """Join two tuple types while handling variadic entries.
472
473 This is surprisingly tricky, and we don't handle some tricky corner cases.
474 Most of the trickiness comes from the variadic tuple items like *tuple[X, ...]
475 since they can have arbitrary partial overlaps (while *Ts can't be split).
476 """
477 s_unpack_index = find_unpack_in_list(s.items)
478 t_unpack_index = find_unpack_in_list(t.items)
479 if s_unpack_index is None and t_unpack_index is None:
480 if s.length() == t.length():
481 items: list[Type] = []
482 for i in range(t.length()):
483 items.append(join_types(t.items[i], s.items[i]))
484 return items
485 return None
486 if s_unpack_index is not None and t_unpack_index is not None:
487 # The most complex case: both tuples have an unpack item.
488 s_unpack = s.items[s_unpack_index]
489 assert isinstance(s_unpack, UnpackType)
490 s_unpacked = get_proper_type(s_unpack.type)
491 t_unpack = t.items[t_unpack_index]
492 assert isinstance(t_unpack, UnpackType)
493 t_unpacked = get_proper_type(t_unpack.type)
494 if s.length() == t.length() and s_unpack_index == t_unpack_index:
495 # We can handle a case where arity is perfectly aligned, e.g.
496 # join(Tuple[X1, *tuple[Y1, ...], Z1], Tuple[X2, *tuple[Y2, ...], Z2]).
497 # We can essentially perform the join elementwise.
498 prefix_len = t_unpack_index
499 suffix_len = t.length() - t_unpack_index - 1
500 items = []
501 for si, ti in zip(s.items[:prefix_len], t.items[:prefix_len]):
502 items.append(join_types(si, ti))
503 joined = join_types(s_unpacked, t_unpacked)
504 if isinstance(joined, TypeVarTupleType):
505 items.append(UnpackType(joined))
506 elif isinstance(joined, Instance) and joined.type.fullname == "builtins.tuple":
507 items.append(UnpackType(joined))
508 else:
509 if isinstance(t_unpacked, Instance):
510 assert t_unpacked.type.fullname == "builtins.tuple"
511 tuple_instance = t_unpacked
512 else:
513 assert isinstance(t_unpacked, TypeVarTupleType)
514 tuple_instance = t_unpacked.tuple_fallback
515 items.append(
516 UnpackType(
517 tuple_instance.copy_modified(
518 args=[object_from_instance(tuple_instance)]
519 )
520 )
521 )
522 if suffix_len:
523 for si, ti in zip(s.items[-suffix_len:], t.items[-suffix_len:]):
524 items.append(join_types(si, ti))
525 return items
526 if s.length() == 1 or t.length() == 1:
527 # Another case we can handle is when one of tuple is purely variadic

Callers 1

visit_tuple_typeMethod · 0.95

Calls 15

find_unpack_in_listFunction · 0.90
get_proper_typeFunction · 0.90
UnpackTypeClass · 0.90
rangeClass · 0.85
join_typesFunction · 0.85
isinstanceFunction · 0.85
zipFunction · 0.85
object_from_instanceFunction · 0.85
enumerateFunction · 0.85
join_type_listFunction · 0.85
tupleClass · 0.85

Tested by

no test coverage detected