diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 800868b28d7a..adcc0c14d661 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -22089,10 +22089,16 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions const destUnboundedOrVariadicIndex = destTypeArgs.findIndex((t) => t.isUnbounded || isVariadicTypeVar(t.type)); const srcUnboundedIndex = srcTypeArgs.findIndex((t) => t.isUnbounded); const srcVariadicIndex = srcTypeArgs.findIndex((t) => isVariadicTypeVar(t.type)); + let isSrcVariadicAny = false; // If the src contains an unbounded type but the dest does not, it's incompatible. if (srcUnboundedIndex >= 0 && destUnboundedOrVariadicIndex < 0) { - return false; + // Unless the source contains an [Any, ...]. + if (isAnyOrUnknown(srcTypeArgs[srcUnboundedIndex].type)) { + isSrcVariadicAny = true; + } else { + return false; + } } if (srcUnboundedIndex >= 0) { @@ -22103,6 +22109,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions while (srcTypeArgs.length < destTypeArgs.length) { srcTypeArgs.splice(srcUnboundedIndex, 0, { type: typeToReplicate, isUnbounded: true }); } + + if (isSrcVariadicAny && srcTypeArgs.length > destTypeArgs.length) { + srcTypeArgs.splice(srcUnboundedIndex, 1); + } } // Remove any optional parameters from the end of the two lists until the lengths match. diff --git a/packages/pyright-internal/src/tests/samples/tuple1.py b/packages/pyright-internal/src/tests/samples/tuple1.py index 390e376f381d..fb65d68da958 100644 --- a/packages/pyright-internal/src/tests/samples/tuple1.py +++ b/packages/pyright-internal/src/tests/samples/tuple1.py @@ -1,7 +1,7 @@ # This sample file tests various aspects of type analysis for tuples. import os -from typing import Callable +from typing import Any, Callable from typing_extensions import TypeVarTuple, Unpack Ts = TypeVarTuple("Ts") @@ -226,3 +226,20 @@ def func17(var: tuple[int, ...]) -> str: f1 = func16 f1 = func17 + + +def func18(a: tuple[int, *tuple[Any, ...], str], b: tuple[Any, ...]): + a1: tuple[int, str] = a + a2: tuple[int, int, str] = a + a3: tuple[int, int, str, str] = a + a4: tuple[int, *tuple[int, ...], str] = a + + # This should generate an error. + a5: tuple[str, int, str, str] = a + + # This should generate an error. + a6: tuple[int, int, str, int] = a + + b1: tuple[()] = b + b2: tuple[int, int, str] = b + b3: tuple[int, *tuple[int, ...], str] = b diff --git a/packages/pyright-internal/src/tests/samples/variadicTypeVar10.py b/packages/pyright-internal/src/tests/samples/variadicTypeVar10.py index 3b23f9fd5877..549cb8f9ef20 100644 --- a/packages/pyright-internal/src/tests/samples/variadicTypeVar10.py +++ b/packages/pyright-internal/src/tests/samples/variadicTypeVar10.py @@ -62,6 +62,4 @@ def func4(y: Array[Any, Unpack[tuple[Any, ...]]]): reveal_type(y, expected_text="Array[Any, *tuple[Any, ...]]") expect_variadic_array1(y) expect_variadic_array2(y) - - # This should generate an error because of a tuple size mismatch. expect_precise_array(y) diff --git a/packages/pyright-internal/src/tests/typeEvaluator1.test.ts b/packages/pyright-internal/src/tests/typeEvaluator1.test.ts index c107ceaec50f..d2a75e39c301 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator1.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator1.test.ts @@ -1270,7 +1270,7 @@ test('Optional2', () => { test('Tuple1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['tuple1.py']); - TestUtils.validateResults(analysisResults, 15); + TestUtils.validateResults(analysisResults, 17); }); test('Tuple2', () => { diff --git a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts index e4ebe0c0afae..567db4517fa2 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts @@ -1115,7 +1115,7 @@ test('VariadicTypeVar10', () => { configOptions.defaultPythonVersion = PythonVersion.V3_11; const analysisResults = TestUtils.typeAnalyzeSampleFiles(['variadicTypeVar10.py'], configOptions); - TestUtils.validateResults(analysisResults, 3); + TestUtils.validateResults(analysisResults, 2); }); test('VariadicTypeVar11', () => {