Skip to content

Commit e4900ba

Browse files
committed
Fix joining of fixed tuples with mismatching lengths
For example: Tuple[bool, int] + Tuple[bool] becomes Tuple[int, ...] Previously Mypy simply punted and returned `object`. The other missing handling of fixed tuple + variadic tuple will be implemented separately.
1 parent 41b40aa commit e4900ba

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

mypy/join.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -260,14 +260,28 @@ def visit_overloaded(self, t: Overloaded) -> ProperType:
260260
return join_types(t.fallback, s)
261261

262262
def visit_tuple_type(self, t: TupleType) -> ProperType:
263-
if isinstance(self.s, TupleType) and self.s.length() == t.length():
264-
items = [] # type: List[Type]
265-
for i in range(t.length()):
266-
items.append(self.join(t.items[i], self.s.items[i]))
267-
fallback = join_instances(mypy.typeops.tuple_fallback(self.s),
268-
mypy.typeops.tuple_fallback(t))
269-
assert isinstance(fallback, Instance)
270-
return TupleType(items, fallback)
263+
# When given two fixed-length tuples:
264+
# * If lengths match, join their subtypes item-wise:
265+
# Tuple[int, bool] + Tuple[bool, bool] becomes Tuple[int, bool]
266+
# * If lengths do not match, return a variadic tuple:
267+
# Tuple[bool, int] + Tuple[bool] becomes Tuple[int, ...]
268+
# * Fixed tuple + variadic tuple is currently not implemented.
269+
if isinstance(self.s, TupleType):
270+
if self.s.length() == t.length():
271+
items = [] # type: List[Type]
272+
for i in range(t.length()):
273+
items.append(self.join(t.items[i], self.s.items[i]))
274+
fallback = join_instances(mypy.typeops.tuple_fallback(self.s),
275+
mypy.typeops.tuple_fallback(t))
276+
assert isinstance(fallback, Instance)
277+
return TupleType(items, fallback)
278+
else:
279+
items = self.s.items + t.items
280+
# Otherwise they'd compare equal in above check.
281+
assert len(items), "Both tuple items cannot be empty"
282+
subtype = join_type_list(items)
283+
tuple_type = self.s.partial_fallback.type # FIXME how do I construct TypeInfo?
284+
return Instance(tuple_type, [subtype])
271285
else:
272286
return self.default(self.s)
273287

mypy/test/testtypes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ def test_tuples(self) -> None:
504504
self.fx.o)
505505
self.assert_join(self.tuple(self.fx.a),
506506
self.tuple(self.fx.a, self.fx.a),
507-
self.fx.o)
507+
Instance(self.fx.std_tuplei, [self.fx.a]))
508508

509509
def test_function_types(self) -> None:
510510
self.assert_join(self.callable(self.fx.a, self.fx.b),

0 commit comments

Comments
 (0)