Summary
Complete PEP 798 unpacking operands and selected Python 3.15 parser diagnostics on the RustPython 0.17.1 parser branch.
The original operand changes accept full expressions in dictionary comprehensions and starred generator expressions, preserving deferred-error ordering and valid recovered AST ranges. The appended diagnostics cover:
- Parameter terminology and repeated-star wording.
- Standalone
case clauses, assertion assignment/walrus syntax, mapping-rest ordering, and misplaced lazy imports.
- Unclosed multiline f-string/t-string replacement fields, identifying the opening brace's line.
- Missing-comma hints after multiline literal concatenation, displayed on the final literal line without changing original-expression error precedence.
Diagnostic speculation restores parser recovery state. Existing raise/from and trailing-with diagnostics retain their messages and ranges while gaining structured variants for standalone-case inner-error selection. No new Cargo feature or diagnostic version gate is introduced.
The oracle is CPython 3.15.0 at d220409a13b77de7a6c30abe16ea90db01528edc, including its grammar, replacement-field tests, and syntax tests. This builds on rustpython-0.17.1; older-version work in #6 remains separate. RustPython consumers still need the resulting revision and separate compiler/VM integration; this is not a crates.io release.
Validation of the appended diagnostics
Baseline: existing PR head e72c1058999264cad17a01119a6fa57b3946a493.
- Unchanged baseline: 617 parser fixture tests passed.
- Candidate: 643 parser fixture tests passed with snapshot updates disabled after reviewing the generated snapshots.
- All 22 snapshots changed by the original PEP 798 work remain byte-identical. All 14 changed existing diagnostic snapshots retain their AST sections.
- Four selected canonical CPython methods passed, covering 48 multiline replacement-field cases, multiline concatenation, and valid
case()/match() calls. Their 51 compile calls were recorded without executing payloads and included in the finite native-parser comparison.
- Across 90 finite sources, the candidate's first diagnostic message matches CPython in 85 cases, versus 19 on the baseline. All 90 recovered AST and token streams are identical between baseline and candidate.
- Parser-only strict all-target Clippy passed with
--no-deps. Dependency-wide strict Clippy failed on the same nine unexpected_cfgs errors for cache/salsa in both the exact baseline and candidate; the AST dependency is unchanged.
- The exact existing
parser::tests::cells_module_range_spans_source unit passed: one executed, 253 filtered. No other parser unit or workspace runtime suite was rerun.
- Normal configured changed-file hooks passed without modifying the validated source; logical commits also use the installed hooks.
Five comparison cases retain pre-existing classification/priority differences: unclosed assertion RHS; an assertion RHS with an invalid f-string escape; a slash-only parameter list without a comma; an unclosed misplaced-lazy import list; and a misplaced-lazy alias containing an invalid f-string escape. Four complete error lists are unchanged. The slash-only list retains the pre-existing overbroad error classification with updated parameter wording. This change does not claim complete diagnostic parity.
Earlier PEP 798 validation
Before the appended diagnostics, the existing head passed 254 unit tests, 617 fixture tests, one integration test, and ten doctests; parser-only strict Clippy; and normal commit hooks. Its separate RustPython integration passed canonical test_unpack_ex, 41 compile/error-order observations, eight bytecode/position observations, 482 related tests with 18 existing skips, and 31 selected async-generator tests. Those are historical results for the original operand change, not newly rerun proof for this append. The RustPython integration includes compiler changes outside this parser PR.
Assistance
Prepared and tested with OpenAI Codex at the maintainer's explicit request for the RustPython-managed fork. No claim of manual maintainer review is implied.