Skip to content

Commit

Permalink
Fix handling of tuple type context with unpacks (#16444)
Browse files Browse the repository at this point in the history
Fixes #16425

Fix is straightforward.
  • Loading branch information
ilevkivskyi authored and JukkaL committed Nov 10, 2023
1 parent c22294a commit 62bcae2
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
10 changes: 5 additions & 5 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4902,7 +4902,7 @@ def tuple_context_matches(self, expr: TupleExpr, ctx: TupleType) -> bool:
return len([e for e in expr.items if not isinstance(e, StarExpr)]) <= len(ctx.items)
# For variadic context, the only easy case is when structure matches exactly.
# TODO: try using tuple type context in more cases.
if len([e for e in expr.items if not isinstance(e, StarExpr)]) != 1:
if len([e for e in expr.items if isinstance(e, StarExpr)]) != 1:
return False
expr_star_index = next(i for i, lv in enumerate(expr.items) if isinstance(lv, StarExpr))
return len(expr.items) == len(ctx.items) and ctx_unpack_index == expr_star_index
Expand Down Expand Up @@ -4941,6 +4941,9 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
if type_context_items is not None:
unpack_in_context = find_unpack_in_list(type_context_items) is not None
seen_unpack_in_items = False
allow_precise_tuples = (
unpack_in_context or PRECISE_TUPLE_TYPES in self.chk.options.enable_incomplete_feature
)

# Infer item types. Give up if there's a star expression
# that's not a Tuple.
Expand Down Expand Up @@ -4981,10 +4984,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
# result in an error later, just do something predictable here.
j += len(tt.items)
else:
if (
PRECISE_TUPLE_TYPES in self.chk.options.enable_incomplete_feature
and not seen_unpack_in_items
):
if allow_precise_tuples and not seen_unpack_in_items:
# Handle (x, *y, z), where y is e.g. tuple[Y, ...].
if isinstance(tt, Instance) and self.chk.type_is_iterable(tt):
item_type = self.chk.iterable_item_type(tt, e)
Expand Down
10 changes: 10 additions & 0 deletions test-data/unit/check-typevar-tuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -2225,3 +2225,13 @@ bar(*keys, 1) # OK
reveal_type(baz(keys, 1)) # N: Revealed type is "builtins.object"
reveal_type(baz(*keys, 1)) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]

[case testVariadicTupleContextNoCrash]
from typing import Tuple, Unpack

x: Tuple[int, Unpack[Tuple[int, ...]]] = () # E: Incompatible types in assignment (expression has type "Tuple[()]", variable has type "Tuple[int, Unpack[Tuple[int, ...]]]")
y: Tuple[int, Unpack[Tuple[int, ...]]] = (1, 2)
z: Tuple[int, Unpack[Tuple[int, ...]]] = (1,)
w: Tuple[int, Unpack[Tuple[int, ...]]] = (1, *[2, 3, 4])
t: Tuple[int, Unpack[Tuple[int, ...]]] = (1, *(2, 3, 4))
[builtins fixtures/tuple.pyi]

0 comments on commit 62bcae2

Please sign in to comment.