fix(checker): avoid false overload-cannot-match with ParamSpec args#21194
Open
Bahtya wants to merge 2 commits intopython:masterfrom
Open
fix(checker): avoid false overload-cannot-match with ParamSpec args#21194Bahtya wants to merge 2 commits intopython:masterfrom
Bahtya wants to merge 2 commits intopython:masterfrom
Conversation
When an overload uses ParamSpec-flavored *args (P.args) or **kwargs (P.kwargs), erasing the ParamSpec to Any makes the signature appear to accept all arguments. This causes a false 'overload will never be matched' error when combined with a second overload that has explicit keyword-only parameters. Skip the can-never-match check when the first overload has ParamSpec-flavored variadic arguments, since we cannot reliably determine overlap after erasure. Fixes python#21171 Signed-off-by: bahtya <bahtyar153@qq.com>
for more information, see https://pre-commit.ci
Contributor
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Author
|
Hi mypy maintainers! Friendly ping on this PR. To summarize for ease of review:
Happy to make any adjustments if needed. Thanks for your time! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When an overload uses ParamSpec-flavored
*args(P.args) or**kwargs(P.kwargs), mypy incorrectly reports that a second overload with explicit keyword-only parameters "will never be matched":Output:
Root Cause
overload_can_never_matcherases type variables by expanding them (erase_def_to_union_or_bound). ForParamSpec, this erases toAny, so*a: P.argsand**k: P.kwargsbecome*a: Anyand**k: Any. This makes the first overload appear to accept all possible arguments — including thebazkeyword argument — causing mypy to conclude (incorrectly) that the second overload can never be reached.In reality,
P.kwargsis constrained to the wrapped functionf's actual keyword parameters, so a call withbaz=5would NOT match the first overload iffdoesn't accept abazparameter.Solution
In
overload_can_never_match, check if the signature has ParamSpec-flavored variadic arguments (P.argsorP.kwargs). If so, skip the can-never-match check, since we cannot reliably determine overlap after erasing ParamSpec toAny.Testing
testOverloadParamSpecNoFalsePositiveCannotMatchtest case incheck-parameter-specification.testFixes #21171