Skip to content

Conversation

@sterliakov
Copy link
Collaborator

@sterliakov sterliakov commented Oct 25, 2025

Fixes #19839.

Looks like it was relatively easy to do the right way, let me try! When splitting a callable/parameters into args and kwargs, we have the following options:

  • posonly - only goes to *args, required unless has a default. If we encounter such required arg, all previously collected optional args become required (this only happens due to faulty TVT expansion somewhere; probably I should look into that too)
  • kwonly - only goes to **kwargs, required unless has a default
  • pos-or-kw - goes to both
  • vararg - only goes to *args as an Unpack (possibly normalized by tuple constructor)
  • kwargs - only goes to **kwargs and is only used if there are no kwargs with known names, because PEP 728 is not yet implemented, so we have to choose between dict and TypedDict. (thoughts? Maybe it is better to prefer dict with union(kwarg, *kwargs.values()) as value type? Either way I do not consider this question important as PEP728 will be eventually implemented, and we'll have extra_items for our TypedDicts)

Applying these steps to every argument in order, we collect required and optional args and kwargs candidates. Now, the type of **kwargs is a TypedDict if we know any keys, dict[str, KwargType] if we only have something like **kw: str, and dict[str, Never] if no kwargs were found.

The type of *args is union of all prefixes of optional_args concatenated with required_args: all required args must be there, and optional args can only be passed in order. Since it is uncommon to have a function with more than 10-20 args, I think this union is a reasonable solution.

@sterliakov sterliakov marked this pull request as ready for review October 25, 2025 22:19
@github-actions
Copy link
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

TupleType(required_posargs + optional_posargs[:i], fallback=t.upper_bound)
for i in range(len(optional_posargs) + 1)
]
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please refactor these two new flavor branches into helper functions (and possible add a bit more explanation there)? Right now this visitor method is big and hard to follow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(essentially think about how to turn part of the PR description into two nice docstrings)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AssertionError when using reveal_type on a class-bound ParamSpec.

2 participants