diff --git a/packages/pyright-internal/src/analyzer/patternMatching.ts b/packages/pyright-internal/src/analyzer/patternMatching.ts index c86f7cd7140e..55ae16160e1c 100644 --- a/packages/pyright-internal/src/analyzer/patternMatching.ts +++ b/packages/pyright-internal/src/analyzer/patternMatching.ts @@ -109,6 +109,7 @@ interface SequencePatternInfo { entryTypes: Type[]; isIndeterminateLength?: boolean; isTuple?: boolean; + isUnboundedTuple?: boolean; } interface MappingPatternInfo { @@ -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; } @@ -1436,6 +1437,7 @@ function getSequencePatternInfo( entryTypes: isDefiniteNoMatch ? [] : typeArgs.map((t) => t.type), isIndeterminateLength: false, isTuple: true, + isUnboundedTuple: tupleIndeterminateIndex >= 0, isDefiniteNoMatch, isPotentialNoMatch, }); @@ -1488,6 +1490,7 @@ function getSequencePatternInfo( entryTypes: isDefiniteNoMatch ? [] : typeArgs.map((t) => t.type), isIndeterminateLength: false, isTuple: true, + isUnboundedTuple: tupleIndeterminateIndex >= 0, isDefiniteNoMatch, }); return; diff --git a/packages/pyright-internal/src/tests/samples/matchSequence1.py b/packages/pyright-internal/src/tests/samples/matchSequence1.py index 13ebdcc2b3fd..6a2d3b57255b 100644 --- a/packages/pyright-internal/src/tests/samples/matchSequence1.py +++ b/packages/pyright-internal/src/tests/samples/matchSequence1.py @@ -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: