Variadic keyword generics - #51
Merged
Merged
Conversation
unpack keyword packs with `**`, matching the declaration
`**kwargs: **Kwargs` is now the spelling — the star count follows the pack's
declaration (`[**Kwargs]`), the way `*args: *Ts` follows `[*Ts]`. the single
star was the TypeVarTuple spelling and no longer parses on a pack, so there is
one way to write it
`{**Kwargs}` (splicing a pack into a dict literal type) gets a real diagnostic
instead of two misleading ones. it is not supported: a synthesized TypedDict is
a `ClassType::NonGeneric` by construction, so a specialization never reaches its
schema — the same gap leaves `T` unsubstituted in `{"a": T}`
infer keyword packs from constructor keyword arguments
`**kwargs: *Kwargs` unpacks a keyword-variadic pack into a parameter list, so
`A(a=1, b="s")` now solves `Kwargs` to `(a=int, b=str)`. the single `*` unpacks
the variadic, mirroring `*args: *Ts`
the pack is solved as a whole rather than per-argument — the per-argument path
would bind it to one field's type. an already-specialized pack expands into
keyword-only parameters through the existing starred-annotation hook, so the
constructor call is checked against the fields
lowers to the runtime `ParamSpec` spelling `**kwargs: Kwargs.kwargs`
drive-by, both pre-existing and both needed by the above:
- `init(*args)` / `init(**kwargs)` read the `*` as a parameter modifier and
failed with "`*` is not a valid modifier on an `init` parameter"
- the pep695 polyfill's typevar rename skipped vararg/kwarg annotations, so a
polyfilled `**kwargs: Kwargs.kwargs` kept the pre-rename name
snapshot the bare keyword-pack diagnostic
it carries subdiagnostics, so pin them rather than only the primary message
added keyword-variadic packs (`class A[**Kwargs]`)
in a `.by` file the pep-695 `**Name` spelling now declares a keyword-variadic
pack — an ordered name→type mapping — instead of a `ParamSpec`. specialized by
keyword (`A[foo=int, bar=str]`), unpacked with `**` in a callable arrow, where
its fields become keyword-only parameters
reuses the paramspec engine: a pack's value is the same callable-shaped value,
so relations, variance, substitution and concatenate all come along. the split
is `is_parameter_pack` (callable-shaped value) vs `is_paramspec` (truthful)
confined to `.by`; `.byi` keeps `ParamSpec` for typeshed interop
`class A[**P]` in a .py file now reverses to `class A[P: (*: *, **: *)]` — an anonymous variadic and an anonymous keyword-variadic, both admitting anything. every parameter list is a subtype of it, so the bound ranges over all parameter lists, which is exactly a ParamSpec. `[**P]` could not stay as-is: in a .by file it declares a keyword-variadic pack the structural form is what docs/basedpython/features/generics.md already documented; the implementation had been recognising a bare `Parameters` marker name instead. that name is now gone, along with the import-stripping it needed — one spelling, no magic name, and the pair round-trips `*` is now accepted as the type of an anonymous parameter field, so `(*: *)` parses; it reuses the top-star marker a subscript `[*]` already produces
`A[(int, foo: str)]` built every field as a positional-only parameter, so `foo: str` came back as a bare `str` and the name could not be passed. it now reveals `A[(int, /, foo: str)]` and `foo` binds by keyword the callable arrow already knew every field form, so both now share one builder, `infer_parameter_spec_elements`. that also fixes the arrow's `*` marker: the keyword-only branch sat behind an `after_star` test that the preceding arm had already claimed, so it was dead and `(int, *, foo: str)` produced a positional `foo` the `/` shown after `int` is real — a bare field has no name to be passed by
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.
No description provided.