Skip to content

Commit

Permalink
Fixed bug that results in incorrect type narrowing for sequence patte…
Browse files Browse the repository at this point in the history
…rns in the negative (fall-through) case when the subject is a tuple with an unbounded entry. This addresses microsoft#8967. (microsoft#8968)
  • Loading branch information
erictraut authored Sep 11, 2024
1 parent d91a24b commit 0d92942
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
5 changes: 4 additions & 1 deletion packages/pyright-internal/src/analyzer/patternMatching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ interface SequencePatternInfo {
entryTypes: Type[];
isIndeterminateLength?: boolean;
isTuple?: boolean;
isUnboundedTuple?: boolean;
}

interface MappingPatternInfo {
Expand Down Expand Up @@ -225,7 +226,7 @@ function narrowTypeBasedOnSequencePattern(
// contains indeterminate-length entries or the tuple is of indeterminate
// length.
if (!isPositiveTest) {
if (entry.isIndeterminateLength) {
if (entry.isIndeterminateLength || entry.isUnboundedTuple) {
canNarrowTuple = false;
}

Expand Down Expand Up @@ -1436,6 +1437,7 @@ function getSequencePatternInfo(
entryTypes: isDefiniteNoMatch ? [] : typeArgs.map((t) => t.type),
isIndeterminateLength: false,
isTuple: true,
isUnboundedTuple: tupleIndeterminateIndex >= 0,
isDefiniteNoMatch,
isPotentialNoMatch,
});
Expand Down Expand Up @@ -1488,6 +1490,7 @@ function getSequencePatternInfo(
entryTypes: isDefiniteNoMatch ? [] : typeArgs.map((t) => t.type),
isIndeterminateLength: false,
isTuple: true,
isUnboundedTuple: tupleIndeterminateIndex >= 0,
isDefiniteNoMatch,
});
return;
Expand Down
18 changes: 18 additions & 0 deletions packages/pyright-internal/src/tests/samples/matchSequence1.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,24 @@ def test_unbounded_tuple_5(subj: tuple[int, Unpack[tuple[str, ...]]]):
reveal_type(x, expected_text="Never")


def test_unbounded_tuple_6(subj: tuple[str, ...]):
match subj:
case ("a", b, _, _):
reveal_type(b, expected_text="str")

case ("a", b, _, _, _):
reveal_type(b, expected_text="str")

case (_, b, _, _):
reveal_type(b, expected_text="str")

case (_, b, _, _, _):
reveal_type(b, expected_text="str")

case r:
reveal_type(r, expected_text="tuple[str, ...]")


def test_variadic_tuple(subj: tuple[int, Unpack[Ts]]) -> tuple[Unpack[Ts]]:
match subj:
case _, *rest:
Expand Down

0 comments on commit 0d92942

Please sign in to comment.