diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index be6a78a021ba..53fa75fa5ec3 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -378,9 +378,15 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType: # tuples, so we instead try to narrow the entire type. # TODO: use more precise narrowing when possible (e.g. for identical shapes). new_tuple_type = TupleType(new_inner_types, current_type.partial_fallback) - new_type, rest_type = self.chk.conditional_types_with_intersection( + new_type, _ = self.chk.conditional_types_with_intersection( new_tuple_type, [get_type_range(current_type)], o, default=new_tuple_type ) + if ( + star_position is not None + and required_patterns <= len(inner_types) - 1 + and all(is_uninhabited(rest) for rest in rest_inner_types) + ): + rest_type = UninhabitedType() else: new_inner_type = UninhabitedType() for typ in new_inner_types: @@ -460,7 +466,7 @@ def expand_starred_pattern_types( # so we only restore the type of the star item. res = [] for i, t in enumerate(types): - if i != star_pos: + if i != star_pos or is_uninhabited(t): res.append(t) else: res.append(UnpackType(self.chk.named_generic_type("builtins.tuple", [t]))) diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 549c54f43a0f..4b8286ce5cc9 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -3136,6 +3136,36 @@ match m3: reveal_type(c3) # N: Revealed type is "builtins.int" [builtins fixtures/tuple.pyi] +[case testMatchSequencePatternVariadicTuple] +# flags: --strict-equality --warn-unreachable +from typing_extensions import Unpack + +def f1(m: tuple[int, Unpack[tuple[str, ...]], int]) -> None: + match m: + case (a1, b1): + reveal_type(m) # N: Revealed type is "tuple[builtins.int, builtins.int]" + case (a2, b2, c2): + reveal_type(m) # N: Revealed type is "tuple[builtins.int, builtins.str, builtins.int]" + case (a3, b3, c3, d3): + reveal_type(m) # N: Revealed type is "tuple[builtins.int, builtins.str, builtins.str, builtins.int]" + case (a4, *b4, c4): + reveal_type(m) # N: Revealed type is "tuple[builtins.int, Unpack[builtins.tuple[builtins.str, ...]], builtins.int]" + case _: + reveal_type(m) # E: Statement is unreachable + + +def f2(m: tuple[int] | tuple[str, str] | tuple[int, Unpack[tuple[str, ...]], int]): + match m: + case (x,): + reveal_type(m) # N: Revealed type is "tuple[builtins.int]" + case (x, y): + reveal_type(m) # N: Revealed type is "tuple[builtins.str, builtins.str] | tuple[builtins.int, builtins.int]" + case (x, y, z): + reveal_type(m) # N: Revealed type is "tuple[builtins.int, builtins.str, builtins.int]" + case _: + reveal_type(m) # N: Revealed type is "tuple[builtins.int, Unpack[builtins.tuple[builtins.str, ...]], builtins.int]" +[builtins fixtures/tuple.pyi] + [case testMatchSequencePatternTypeVarTupleNotTooShort] # flags: --strict-equality --warn-unreachable from typing import Tuple