From 31c98a4ee64b59fbaf4e69c1845684cf0a1afc9c Mon Sep 17 00:00:00 2001 From: Evan Kohilas Date: Thu, 4 Dec 2025 17:39:12 -0800 Subject: [PATCH 1/5] add config to separate builtins --- .../src/analyzer/typeEvaluator.ts | 4 +++- .../src/common/configOptions.ts | 9 +++++++++ .../src/common/diagnosticRules.ts | 1 + .../src/tests/argumentsMatchParamNames.test.ts | 17 +++++++++++++++++ .../tests/samples/argumentsMatchParamNames.py | 3 +++ 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index cb74bbcf3a..b18a81d5b4 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -12303,7 +12303,9 @@ export function createTypeEvaluator( const paramName = argParam.paramName; if (passedName !== paramName) { addDiagnostic( - DiagnosticRule.reportPositionalArgumentNameMismatch, + FunctionType.isBuiltIn(type) + ? DiagnosticRule.reportPositionalArgumentNameMismatchForBuiltIns + : DiagnosticRule.reportPositionalArgumentNameMismatch, `Positional argument "${passedName}" does not match parameter name "${paramName}"; pass as a keyword argument to avoid confusion`, a.valueExpression ); diff --git a/packages/pyright-internal/src/common/configOptions.ts b/packages/pyright-internal/src/common/configOptions.ts index 1cf509dd15..727b435ddc 100644 --- a/packages/pyright-internal/src/common/configOptions.ts +++ b/packages/pyright-internal/src/common/configOptions.ts @@ -207,6 +207,9 @@ export interface DiagnosticRuleSet { // Report mismatch between positional argument names and parameter names when requested by decorator? reportPositionalArgumentNameMismatch: DiagnosticLevel; + // Report mismatch between positional argument names and parameter names for built-in functions? + reportPositionalArgumentNameMismatchForBuiltIns: DiagnosticLevel; + // Report inconsistencies with function overload signatures? reportInconsistentOverload: DiagnosticLevel; @@ -625,6 +628,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'none', reportCallIssue: 'none', reportPositionalArgumentNameMismatch: 'none', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'none', reportIndexIssue: 'none', reportInvalidTypeArguments: 'none', @@ -745,6 +749,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'none', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', @@ -865,6 +870,7 @@ export function getStandardDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'none', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', @@ -1060,6 +1066,7 @@ export const getRecommendedDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'none', // TODO: change to error when we're confident there's no performance issues with this rule reportInvalidAbstractMethod: 'warning', reportPositionalArgumentNameMismatch: 'warning', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', allowedUntypedLibraries: [], }); @@ -1176,6 +1183,7 @@ export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'error', reportInvalidAbstractMethod: 'error', reportPositionalArgumentNameMismatch: 'error', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', allowedUntypedLibraries: [], }); @@ -1217,6 +1225,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'warning', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', diff --git a/packages/pyright-internal/src/common/diagnosticRules.ts b/packages/pyright-internal/src/common/diagnosticRules.ts index be554ec28f..ea2eee7c42 100644 --- a/packages/pyright-internal/src/common/diagnosticRules.ts +++ b/packages/pyright-internal/src/common/diagnosticRules.ts @@ -105,6 +105,7 @@ export enum DiagnosticRule { reportShadowedImports = 'reportShadowedImports', reportImplicitOverride = 'reportImplicitOverride', reportPositionalArgumentNameMismatch = 'reportPositionalArgumentNameMismatch', + reportPositionalArgumentNameMismatchForBuiltIns = 'reportPositionalArgumentNameMismatchForBuiltIns', // basedpyright options: failOnWarnings = 'failOnWarnings', diff --git a/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts b/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts index 632875e611..424c089988 100644 --- a/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts +++ b/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts @@ -19,3 +19,20 @@ test('it reports an error', () => { ], }); }); + +test('it reports an error for built-in functions', () => { + const configOptions = new ConfigOptions(Uri.empty()); + configOptions.diagnosticRuleSet.reportPositionalArgumentNameMismatchForBuiltIns = 'warning'; + configOptions.diagnosticRuleSet.reportUnusedParameter = 'none'; + + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['argumentsMatchParamNames.py'], configOptions); + + TestUtils.validateResultsButBased(analysisResults, { + warnings: [ + { + line: 25, + code: DiagnosticRule.reportPositionalArgumentNameMismatchForBuiltIns, + }, + ], + }); +}); diff --git a/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py b/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py index a1cc5c0c3e..9ab4fa8787 100644 --- a/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py +++ b/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py @@ -21,3 +21,6 @@ def foo( height, # okay, matches width=length, # okay, using keyword ) + +iterable = [] +len(iterable) # okay, built-in function From 403eab6e76cbbc2f5f63330480540d267e050aec Mon Sep 17 00:00:00 2001 From: Evan Kohilas Date: Thu, 4 Dec 2025 17:46:15 -0800 Subject: [PATCH 2/5] Apply suggestions from code review update config for builtin --- packages/pyright-internal/src/common/configOptions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pyright-internal/src/common/configOptions.ts b/packages/pyright-internal/src/common/configOptions.ts index 727b435ddc..550ac23695 100644 --- a/packages/pyright-internal/src/common/configOptions.ts +++ b/packages/pyright-internal/src/common/configOptions.ts @@ -1066,7 +1066,7 @@ export const getRecommendedDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'none', // TODO: change to error when we're confident there's no performance issues with this rule reportInvalidAbstractMethod: 'warning', reportPositionalArgumentNameMismatch: 'warning', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', + reportPositionalArgumentNameMismatchForBuiltIns: 'warning', allowedUntypedLibraries: [], }); @@ -1183,7 +1183,7 @@ export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'error', reportInvalidAbstractMethod: 'error', reportPositionalArgumentNameMismatch: 'error', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', + reportPositionalArgumentNameMismatchForBuiltIns: 'error', allowedUntypedLibraries: [], }); @@ -1225,7 +1225,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'warning', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', + reportPositionalArgumentNameMismatchForBuiltIns: 'warning', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', From 895081cb16d41b2aa03cd834fa9c3d148c96ff56 Mon Sep 17 00:00:00 2001 From: Evan Kohilas Date: Thu, 4 Dec 2025 22:37:05 -0800 Subject: [PATCH 3/5] Revert "Apply suggestions from code review " This reverts commit 403eab6e76cbbc2f5f63330480540d267e050aec. --- packages/pyright-internal/src/common/configOptions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pyright-internal/src/common/configOptions.ts b/packages/pyright-internal/src/common/configOptions.ts index 550ac23695..727b435ddc 100644 --- a/packages/pyright-internal/src/common/configOptions.ts +++ b/packages/pyright-internal/src/common/configOptions.ts @@ -1066,7 +1066,7 @@ export const getRecommendedDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'none', // TODO: change to error when we're confident there's no performance issues with this rule reportInvalidAbstractMethod: 'warning', reportPositionalArgumentNameMismatch: 'warning', - reportPositionalArgumentNameMismatchForBuiltIns: 'warning', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', allowedUntypedLibraries: [], }); @@ -1183,7 +1183,7 @@ export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'error', reportInvalidAbstractMethod: 'error', reportPositionalArgumentNameMismatch: 'error', - reportPositionalArgumentNameMismatchForBuiltIns: 'error', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', allowedUntypedLibraries: [], }); @@ -1225,7 +1225,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'warning', - reportPositionalArgumentNameMismatchForBuiltIns: 'warning', + reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', From 5f8347a56e20f391f827ca58ccfb64c8419c3ab0 Mon Sep 17 00:00:00 2001 From: Evan Kohilas Date: Thu, 4 Dec 2025 22:37:16 -0800 Subject: [PATCH 4/5] Revert "add config to separate builtins" This reverts commit 31c98a4ee64b59fbaf4e69c1845684cf0a1afc9c. --- .../src/analyzer/typeEvaluator.ts | 4 +--- .../src/common/configOptions.ts | 9 --------- .../src/common/diagnosticRules.ts | 1 - .../src/tests/argumentsMatchParamNames.test.ts | 17 ----------------- .../tests/samples/argumentsMatchParamNames.py | 3 --- 5 files changed, 1 insertion(+), 33 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index b18a81d5b4..cb74bbcf3a 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -12303,9 +12303,7 @@ export function createTypeEvaluator( const paramName = argParam.paramName; if (passedName !== paramName) { addDiagnostic( - FunctionType.isBuiltIn(type) - ? DiagnosticRule.reportPositionalArgumentNameMismatchForBuiltIns - : DiagnosticRule.reportPositionalArgumentNameMismatch, + DiagnosticRule.reportPositionalArgumentNameMismatch, `Positional argument "${passedName}" does not match parameter name "${paramName}"; pass as a keyword argument to avoid confusion`, a.valueExpression ); diff --git a/packages/pyright-internal/src/common/configOptions.ts b/packages/pyright-internal/src/common/configOptions.ts index 727b435ddc..1cf509dd15 100644 --- a/packages/pyright-internal/src/common/configOptions.ts +++ b/packages/pyright-internal/src/common/configOptions.ts @@ -207,9 +207,6 @@ export interface DiagnosticRuleSet { // Report mismatch between positional argument names and parameter names when requested by decorator? reportPositionalArgumentNameMismatch: DiagnosticLevel; - // Report mismatch between positional argument names and parameter names for built-in functions? - reportPositionalArgumentNameMismatchForBuiltIns: DiagnosticLevel; - // Report inconsistencies with function overload signatures? reportInconsistentOverload: DiagnosticLevel; @@ -628,7 +625,6 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'none', reportCallIssue: 'none', reportPositionalArgumentNameMismatch: 'none', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'none', reportIndexIssue: 'none', reportInvalidTypeArguments: 'none', @@ -749,7 +745,6 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'none', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', @@ -870,7 +865,6 @@ export function getStandardDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'none', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', @@ -1066,7 +1060,6 @@ export const getRecommendedDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'none', // TODO: change to error when we're confident there's no performance issues with this rule reportInvalidAbstractMethod: 'warning', reportPositionalArgumentNameMismatch: 'warning', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', allowedUntypedLibraries: [], }); @@ -1183,7 +1176,6 @@ export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({ reportIncompatibleUnannotatedOverride: 'error', reportInvalidAbstractMethod: 'error', reportPositionalArgumentNameMismatch: 'error', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', allowedUntypedLibraries: [], }); @@ -1225,7 +1217,6 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet { reportAttributeAccessIssue: 'error', reportCallIssue: 'error', reportPositionalArgumentNameMismatch: 'warning', - reportPositionalArgumentNameMismatchForBuiltIns: 'none', reportInconsistentOverload: 'error', reportIndexIssue: 'error', reportInvalidTypeArguments: 'error', diff --git a/packages/pyright-internal/src/common/diagnosticRules.ts b/packages/pyright-internal/src/common/diagnosticRules.ts index ea2eee7c42..be554ec28f 100644 --- a/packages/pyright-internal/src/common/diagnosticRules.ts +++ b/packages/pyright-internal/src/common/diagnosticRules.ts @@ -105,7 +105,6 @@ export enum DiagnosticRule { reportShadowedImports = 'reportShadowedImports', reportImplicitOverride = 'reportImplicitOverride', reportPositionalArgumentNameMismatch = 'reportPositionalArgumentNameMismatch', - reportPositionalArgumentNameMismatchForBuiltIns = 'reportPositionalArgumentNameMismatchForBuiltIns', // basedpyright options: failOnWarnings = 'failOnWarnings', diff --git a/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts b/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts index 424c089988..632875e611 100644 --- a/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts +++ b/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts @@ -19,20 +19,3 @@ test('it reports an error', () => { ], }); }); - -test('it reports an error for built-in functions', () => { - const configOptions = new ConfigOptions(Uri.empty()); - configOptions.diagnosticRuleSet.reportPositionalArgumentNameMismatchForBuiltIns = 'warning'; - configOptions.diagnosticRuleSet.reportUnusedParameter = 'none'; - - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['argumentsMatchParamNames.py'], configOptions); - - TestUtils.validateResultsButBased(analysisResults, { - warnings: [ - { - line: 25, - code: DiagnosticRule.reportPositionalArgumentNameMismatchForBuiltIns, - }, - ], - }); -}); diff --git a/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py b/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py index 9ab4fa8787..a1cc5c0c3e 100644 --- a/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py +++ b/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py @@ -21,6 +21,3 @@ def foo( height, # okay, matches width=length, # okay, using keyword ) - -iterable = [] -len(iterable) # okay, built-in function From dc482b79ad20a5392894a04b687d6021502dae02 Mon Sep 17 00:00:00 2001 From: Evan Kohilas Date: Thu, 4 Dec 2025 23:13:25 -0800 Subject: [PATCH 5/5] initial work --- .../src/analyzer/typeEvaluator.ts | 23 +++++++++++++++---- .../tests/argumentsMatchParamNames.test.ts | 12 ++++++++++ .../tests/samples/argumentsMatchParamNames.py | 12 ++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index cb74bbcf3a..243f1a8088 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -12287,24 +12287,39 @@ export function createTypeEvaluator( skipUnknownArgCheck = true; } + const paramDetails = getParamListDetails(type); matchResults.argParams.forEach((argParam) => { const a = argParam.argument; if ( a.argCategory === ArgCategory.Simple && !a.name && a.valueExpression && - a.valueExpression.nodeType === ParseNodeType.Name && argParam.paramCategory === ParamCategory.Simple && !argParam.mapsToVarArgList && argParam.paramName && !argParam.isParamNameSynthesized ) { - const passedName = (a.valueExpression as NameNode).d.value; + // Skip positional-only parameters + const paramIndex = paramDetails.params.findIndex((p) => p.param.name === argParam.paramName); + if (paramIndex >= 0 && paramIndex < paramDetails.positionOnlyParamCount) { + return; + } + const paramName = argParam.paramName; - if (passedName !== paramName) { + if (a.valueExpression.nodeType === ParseNodeType.Name) { + const passedName = (a.valueExpression as NameNode).d.value; + if (passedName !== paramName) { + addDiagnostic( + DiagnosticRule.reportPositionalArgumentNameMismatch, + `Argument "${passedName}" does not match parameter name "${paramName}" for function "${type.shared.name}"; pass as a keyword argument to avoid confusion`, + a.valueExpression + ); + } + } else { + // Non-name expression passed positionally addDiagnostic( DiagnosticRule.reportPositionalArgumentNameMismatch, - `Positional argument "${passedName}" does not match parameter name "${paramName}"; pass as a keyword argument to avoid confusion`, + `Positional argument for parameter "${paramName}" in function "${type.shared.name}"; pass as a keyword argument to avoid confusion`, a.valueExpression ); } diff --git a/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts b/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts index 632875e611..25f933d99e 100644 --- a/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts +++ b/packages/pyright-internal/src/tests/argumentsMatchParamNames.test.ts @@ -16,6 +16,18 @@ test('it reports an error', () => { line: 11, code: DiagnosticRule.reportPositionalArgumentNameMismatch, }, + { + line: 25, + code: DiagnosticRule.reportPositionalArgumentNameMismatch, + }, + { + line: 32, + code: DiagnosticRule.reportPositionalArgumentNameMismatch, + }, + { + line: 33, + code: DiagnosticRule.reportPositionalArgumentNameMismatch, + }, ], }); }); diff --git a/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py b/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py index a1cc5c0c3e..e4794cff3e 100644 --- a/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py +++ b/packages/pyright-internal/src/tests/samples/argumentsMatchParamNames.py @@ -21,3 +21,15 @@ def foo( height, # okay, matches width=length, # okay, using keyword ) + +foo( + 1, # should display a warning, positional argument used + width=2, # okay, using keyword +) + +len([]) # okay, built-in function with no keyword arguments + +pow( + 2, # should display a warning, positional argument used, built-in function + 3, # should display a warning, positional argument used, built-in function +)