Skip to content

conformance: fix generics_defaults — flag ParamSpec-after-TypeVarTuple when TVT has no default#2310

Open
ashishpatel26 wants to merge 2 commits into
python:mainfrom
ashishpatel26:fix/2211-generics-defaults-paramspec-after-tvt
Open

conformance: fix generics_defaults — flag ParamSpec-after-TypeVarTuple when TVT has no default#2310
ashishpatel26 wants to merge 2 commits into
python:mainfrom
ashishpatel26:fix/2211-generics-defaults-paramspec-after-tvt

Conversation

@ashishpatel26

Copy link
Copy Markdown

Summary

Fixes #2211.

The spec states that a ParamSpec with a default may follow a TypeVarTuple only when the TypeVarTuple also has a default (to avoid ambiguity). The existing conformance test class Foo6(Generic[*Ts, P]) had Ts without a default but was missing an # E marker, effectively telling type checkers to accept code that raises TypeError at runtime.

Changes:

  • conformance/tests/generics_defaults.py

    • Add TsD = TypeVarTuple("TsD", default=Unpack[tuple[int, str]]) for the valid case.
    • Mark class Foo6(Generic[*Ts, P]) as # ETs has no default, so this is ambiguous.
    • Add class Foo6b(Generic[*TsD, P]) (no error) — both TsD and P carry defaults.
    • Replace test_foo6 (which exercised the now-invalid class) with test_foo6b.
  • docs/spec/generics.rst

    • Tighten the prose: "TypeVarTuple with a default" (was missing the emphasis).
    • Add a counter-example class Bar[*Ts, **P = [float, bool]]: ... # Type checker error.
  • conformance/results/*/generics_defaults.toml — updated for all six checkers.

Test plan

  • conformance/tests/generics_defaults.py changes reviewed for correctness
  • All six checker TOMLs updated to reflect new expected/unexpected errors
  • CI "Assert conformance results are up to date" passes (Linux paths use ./)

…le without TVT default

The conformance test for `class Foo6(Generic[*Ts, P])` was missing an
`# E` marker.  The spec only permits a defaulted `ParamSpec` to follow a
`TypeVarTuple` when the `TypeVarTuple` **also has a default**; in the
test `Ts` had no default, so the class is ambiguous (exactly like the
`TypeVar`-after-`TypeVarTuple` rule) and raises `TypeError` at runtime.

Changes:
- Add `TsD = TypeVarTuple("TsD", default=Unpack[tuple[int, str]])` for
  the valid case.
- Mark `class Foo6(Generic[*Ts, P])` as `# E` (Ts has no default).
- Add `class Foo6b(Generic[*TsD, P])` as the spec-valid case (both
  `TsD` and `P` have defaults) with corresponding assertions.
- Clarify the spec prose to state the "TypeVarTuple **with a default**"
  condition explicitly and show a counter-example.
- Update all six checker result TOMLs.

Fixes: python#2211
@srittau srittau added the topic: conformance tests Issues with the conformance test suite label Jun 22, 2026
@davidhalter

Copy link
Copy Markdown
Collaborator

This is probably something where the spec was just not worded well enough. There is kind of an implicit default for type var tuples in this case, which is the empty tuple. I don't think the changing the conformance tests makes sense here.

@AlexWaygood

Copy link
Copy Markdown
Member

the consensus in the issue seemed to be that it's a bug in CPython that we should fix there

pyrefly, pyright, and zuban were missing `conformant = "Partial"` after
conformance_automated changed from Pass to Fail.  The validate_results
script requires conformant to be explicitly set when automated is Fail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic: conformance tests Issues with the conformance test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

generics_defaults.py mandates that type checkers should allow a class that raises TypeError at runtime

4 participants