mypy Closed TypedDicts
Implement PEP 728 closed TypedDicts in mypy: the closed flag and extra_items, with checking of construction, access, updates and compatibility.
Results
Each square represents one run. Score is the percentage of runs that pass: 0, 25, 50, 75, or 100 for four runs.
| # | Model | Rollouts | Pass@1 | Score | Time |
|---|---|---|---|---|---|
| 1 | GPT-6 Astra xhigh | 2/4 | 2.5h | ||
| 2 | GPT-6.1 Sol max | 2/4 | 3.9h | ||
| 3 | Claude Opus 5.5 max | 0/4 | 5.0h | ||
| 4 | GPT-5.6 Sol max | 0/4 | 4.2h | ||
| 5 | Gemini 3.8 Flash high | 0/4 | 0.5h | ||
| 6 | Qwen3.8 Max xhigh | 0/4 | 3.6h | ||
| 7 | GLM 5.3 Flash max | 0/4 | 6.4h | ||
| 8 | Muse Spark 1.3 max | 0/4 | 1.5h | ||
| 9 | Kimi K3 max | 0/4 | 3.7h | ||
| 10 | Grok 4.7 xhigh | 0/4 | 0.9h | ||
| 11 | Claude Sonnet 5.5 max | 0/4 | 4.7h |
Background
mypy is the reference static type checker for Python. Every TypedDict it checks today is open: a value may carry arbitrary extra keys, so an in check cannot narrow a union, unpacking with ** may smuggle unexpected keys into a constructor, and a TypedDict cannot be treated as a Mapping of its value types. PEP 728 adds closed=True for TypedDicts that carry no keys beyond those declared. The agent implements it from the commit before upstream's #21382. Closedness threads through assignability, joins and meets, narrowing, construction, incremental mode, the daemon and stubgen, and also aligns TypedDict inheritance with the specification's rules for redeclared, diamond and mixin items.
Task
The agent implements closed for class and functional syntax, alone or with total, inherited by subclasses that do not pass it. TypedDictType gains a public is_closed attribute as a keyword-only constructor argument so existing plugin calls keep working, and closedness becomes part of the type's identity for equality, hashing, serialization and fine-grained dependencies. Closed types display with closed=True appended, stubgen preserves the keyword, and joins and meets stay the tightest TypedDict the rules allow. The extra_items keyword is out of scope. No dependencies may be added, and only the committed HEAD is graded.
Workspace
The offline sandbox (4 CPUs, 8 GB, 8 hours) holds the mypy repository at commit 4c8f9944, an editable install with pinned test requirements, and copies of PEP 728 and the typing specification's TypedDict chapter. Upstream's feature test cases, a seeded case generator and the reference build are held out.
Verification
The committed tree runs through mypy's own test harness with the starter's harness and test data overlaid. 86 hidden upstream cases in check, incremental, fine-grained, diff, serialize and stubgen form are compared with the upstream build: which lines report an error (not message text), exact reveal_type output, and generated stubs as syntax trees. A seeded generator adds 68 checks of assignability, class validity and incremental rechecking. Cases fall into 13 families, from syntax and inheritance through joins and meets, narrowing, display and the public API; each must reach 90%. All 13,858 existing tests that pass on the starter must also pass.
Environment
- Toolchain
- Python
- Compute
- 4 CPUs · 8 GB RAM
- Network
- Offline
- Time limit
- 8 hours
References
- mypy: The type checker the agent extends, starting at the parent of #21382, the upstream change that added closed TypedDicts.
- PEP 728: TypedDict with Typed Extra Items: Defines closed and extra_items; a copy ships in the workspace.
- Python typing specification: TypedDict: The chapter that governs closedness and inheritance; a copy ships in the workspace.