From 125d6549ec6a88ac7b75dae0c390207659c0f847 Mon Sep 17 00:00:00 2001 From: Henry Su Date: Sun, 9 Aug 2026 23:43:33 -0500 Subject: [PATCH] Fix tuple slice type evaluation for slices with start >= stop --- packages/pyright-internal/src/analyzer/tuples.ts | 4 ++-- .../pyright-internal/src/tests/samples/tuple20.py | 15 +++++++++++++++ .../src/tests/typeEvaluator8.test.ts | 6 ++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 packages/pyright-internal/src/tests/samples/tuple20.py diff --git a/packages/pyright-internal/src/analyzer/tuples.ts b/packages/pyright-internal/src/analyzer/tuples.ts index 34060b858dd2..b69bccef8d38 100644 --- a/packages/pyright-internal/src/analyzer/tuples.ts +++ b/packages/pyright-internal/src/analyzer/tuples.ts @@ -550,11 +550,11 @@ export function getSlicedTupleType( const startValue = getTupleSliceParam(evaluator, sliceNode.d.startValue, 0, tupleTypeArgs); const endValue = getTupleSliceParam(evaluator, sliceNode.d.endValue, tupleTypeArgs.length, tupleTypeArgs); - if (startValue === undefined || endValue === undefined || endValue < startValue) { + if (startValue === undefined || endValue === undefined) { return undefined; } - const slicedTypeArgs = tupleTypeArgs.slice(startValue, endValue); + const slicedTypeArgs = startValue < endValue ? tupleTypeArgs.slice(startValue, endValue) : []; return ClassType.cloneAsInstance(specializeTupleClass(tupleType, slicedTypeArgs)); } diff --git a/packages/pyright-internal/src/tests/samples/tuple20.py b/packages/pyright-internal/src/tests/samples/tuple20.py new file mode 100644 index 000000000000..492c7c45b1cf --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/tuple20.py @@ -0,0 +1,15 @@ +# Sample test for tuple slicing with start index >= stop index. + +t: tuple[int, str, bool] = (1, "a", True) + +# Slicing where start >= stop produces an empty tuple (tuple[()]) +# in Python runtime. + +a = t[2:1] +reveal_type(a, expected_text="tuple[()]") + +b = t[-1:-2] +reveal_type(b, expected_text="tuple[()]") + +c = t[5:1] +reveal_type(c, expected_text="tuple[()]") diff --git a/packages/pyright-internal/src/tests/typeEvaluator8.test.ts b/packages/pyright-internal/src/tests/typeEvaluator8.test.ts index 2af5098a6d43..3b908c3bb00e 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator8.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator8.test.ts @@ -610,6 +610,12 @@ test('Tuple19', () => { TestUtils.validateResults(analysisResults, 1); }); +test('Tuple20', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['tuple20.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + test('NamedTuple1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['namedTuple1.py']);