From 7a01bd8739044005516128f2ae0a75fd2b6ec089 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 11 Jul 2023 10:18:39 +0200 Subject: [PATCH] Fixed another ParamSpec-related issue. This addresses #5454. --- .../src/analyzer/typeEvaluator.ts | 31 +++++++++++-------- .../src/tests/samples/paramSpec45.py | 11 +++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index d32b5308438c..ceab74247eb7 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -9384,6 +9384,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions paramSpecScopeId === typeResult.type.details.typeVarScopeId || paramSpecScopeId === typeResult.type.details.constructorTypeVarScopeId ) { + hasParamSpecArgsKwargs = true; paramSpecArgList = []; paramSpecTarget = TypeVarType.cloneForParamSpecAccess( typeResult.type.details.paramSpec, @@ -10041,20 +10042,24 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions reportedArgError = true; } } else if (argList[argIndex].argumentCategory === ArgumentCategory.Simple) { - if (!isDiagnosticSuppressedForNode(errorNode)) { - const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode); - addDiagnostic( - fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, - DiagnosticRule.reportGeneralTypeIssues, - positionParamLimitIndex === 1 - ? Localizer.Diagnostic.argPositionalExpectedOne() - : Localizer.Diagnostic.argPositionalExpectedCount().format({ - expected: positionParamLimitIndex, - }), - argList[argIndex].valueExpression || errorNode - ); + if (paramSpecArgList) { + paramSpecArgList.push(argList[argIndex]); + } else { + if (!isDiagnosticSuppressedForNode(errorNode)) { + const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode); + addDiagnostic( + fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, + DiagnosticRule.reportGeneralTypeIssues, + positionParamLimitIndex === 1 + ? Localizer.Diagnostic.argPositionalExpectedOne() + : Localizer.Diagnostic.argPositionalExpectedCount().format({ + expected: positionParamLimitIndex, + }), + argList[argIndex].valueExpression || errorNode + ); + } + reportedArgError = true; } - reportedArgError = true; } else if (argList[argIndex].argumentCategory === ArgumentCategory.UnpackedList) { // Handle the case where a *args: P.args is passed as an argument to // a function that accepts a ParamSpec. diff --git a/packages/pyright-internal/src/tests/samples/paramSpec45.py b/packages/pyright-internal/src/tests/samples/paramSpec45.py index 835b0bef43d6..ca1923535125 100644 --- a/packages/pyright-internal/src/tests/samples/paramSpec45.py +++ b/packages/pyright-internal/src/tests/samples/paramSpec45.py @@ -19,3 +19,14 @@ def func3(y: str) -> int: print(func1(func2, x="..."), func1(func3, y="...")) + + +def func4(fn: Callable[P, int], *args: P.args, **kwargs: P.kwargs) -> int: + return fn(*args, **kwargs) + + +def func5(x: int, y: int) -> int: + return x + y + + +func5(func4(lambda x: x, 1), func4(lambda x, y: x + y, 2, 3))