MCPcopy Create free account
hub / github.com/python/mypy / meet_tuples

Method meet_tuples

mypy/meet.py:1005–1081  ·  view source on GitHub ↗

Meet 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

1003 return meet_types(t.fallback, s)
1004
1005 def meet_tuples(self, s: TupleType, t: TupleType) -> list[Type] | None:
1006 """Meet two tuple types while handling variadic entries.
1007
1008 This is surprisingly tricky, and we don't handle some tricky corner cases.
1009 Most of the trickiness comes from the variadic tuple items like *tuple[X, ...]
1010 since they can have arbitrary partial overlaps (while *Ts can't be split). This
1011 function is roughly a mirror of join_tuples() w.r.t. to the fact that fixed
1012 tuples are subtypes of variadic ones but not vice versa.
1013 """
1014 s_unpack_index = find_unpack_in_list(s.items)
1015 t_unpack_index = find_unpack_in_list(t.items)
1016 if s_unpack_index is None and t_unpack_index is None:
1017 if s.length() == t.length():
1018 items: list[Type] = []
1019 for i in range(t.length()):
1020 items.append(self.meet(t.items[i], s.items[i]))
1021 return items
1022 return None
1023 if s_unpack_index is not None and t_unpack_index is not None:
1024 # The only simple case we can handle if both tuples are variadic
1025 # is when their structure fully matches. Other cases are tricky because
1026 # a variadic item is effectively a union of tuples of all length, thus
1027 # potentially causing overlap between a suffix in `s` and a prefix
1028 # in `t` (see how this is handled in is_subtype() for details).
1029 # TODO: handle more cases (like when both prefix/suffix are shorter in s or t).
1030 if s.length() == t.length() and s_unpack_index == t_unpack_index:
1031 unpack_index = s_unpack_index
1032 s_unpack = s.items[unpack_index]
1033 assert isinstance(s_unpack, UnpackType)
1034 s_unpacked = get_proper_type(s_unpack.type)
1035 t_unpack = t.items[unpack_index]
1036 assert isinstance(t_unpack, UnpackType)
1037 t_unpacked = get_proper_type(t_unpack.type)
1038 if not (isinstance(s_unpacked, Instance) and isinstance(t_unpacked, Instance)):
1039 return None
1040 meet = self.meet(s_unpacked, t_unpacked)
1041 if not isinstance(meet, Instance):
1042 return None
1043 m_prefix: list[Type] = []
1044 for si, ti in zip(s.items[:unpack_index], t.items[:unpack_index]):
1045 m_prefix.append(meet_types(si, ti))
1046 m_suffix: list[Type] = []
1047 for si, ti in zip(s.items[unpack_index + 1 :], t.items[unpack_index + 1 :]):
1048 m_suffix.append(meet_types(si, ti))
1049 return m_prefix + [UnpackType(meet)] + m_suffix
1050 return None
1051 if s_unpack_index is not None:
1052 variadic = s
1053 unpack_index = s_unpack_index
1054 fixed = t
1055 else:
1056 assert t_unpack_index is not None
1057 variadic = t
1058 unpack_index = t_unpack_index
1059 fixed = s
1060 # If one tuple is variadic one, and the other one is fixed, the meet will be fixed.
1061 unpack = variadic.items[unpack_index]
1062 assert isinstance(unpack, UnpackType)

Callers 1

visit_tuple_typeMethod · 0.95

Calls 12

meetMethod · 0.95
find_unpack_in_listFunction · 0.90
get_proper_typeFunction · 0.90
UnpackTypeClass · 0.90
rangeClass · 0.85
isinstanceFunction · 0.85
zipFunction · 0.85
meet_typesFunction · 0.85
tupleClass · 0.85
appendMethod · 0.80
lengthMethod · 0.45

Tested by

no test coverage detected