Skip to content

Share exception state and callback controls - #9719

Merged
youknowone merged 3 commits into
RustPython:mainfrom
youknowdot:fix/exception-state-controls-20261104
Nov 6, 2026
Merged

youknowone merged 3 commits into
RustPython:mainfrom
youknowdot:fix/exception-state-controls-20261104

Conversation

@youknowdot

@youknowdot youknowdot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Group CPython 3.15 exception state, construction and callback controls.

  • Keep BaseException allocation permissive while rejecting initializer keywords before mutating args. Preserve lazy exception dictionaries through the shared Constructor path, including specialized exception payloads; nonexception allocation is unchanged.

  • Make public BaseException/KeyError formatting propagate callback errors and preserve WTF-8. Snapshot the short type name before argument callbacks. Retain the forgiving internal diagnostic formatter and its buffered-I/O caller.

  • Restore every raw state entry, including dunder attributes, through setattr without stringifying keys. Preserve string-subclass identity and stop at the first setter error.

  • Use dynamic optional notes lookup and dynamic list creation. Use the canonical Python add_note validation wrapper and the typed Rust add_note_str helper; append to the actual list payload rather than an overridden append method.

  • Share exact-tuple identity, exact-list copying and unhinted iterable conversion between tuple construction and exception args assignment. Borrow the original setter input through replacement so temporary-source finalizers cannot run prematurely.

  • Preserve complete args and allocated-empty-dict identity in reduction. ImportError copies state only when adding native fields; AttributeError preserves ordinary dictionary entries while excluding its native obj field.

  • Share bounded type-name diagnostics with CPython's UTF-8 byte limits and None spelling.

  • Retain the originally installed args tuple through initializer callbacks. SystemExit preserves existing code on empty reinitialization and shares the exact multiargument tuple; StopIteration retains extra incoming owners until value publication.

  • Initialize AttributeError, ImportError and NameError args before rejecting keyword errors, then reuse ArgSpec for maximum-count and insertion-order validation while retaining raw keyword owners. ImportError derives msg from the original tuple even if old-args cleanup reenters initialization.

Validation

Reference source: CPython d220409a13b77de7a6c30abe16ea90db01528edc. Independent source review passed for the frozen four-file patch, including ownership, callback order, locks, dictionary allocation, typed APIs and existing-peer scope.

The reference oracle passed 32 checkpoints, including three explicitly excluded residual controls. Five implementation supplements, ten byte-boundary diagnostics and nine independent supplementary checkpoints also passed on CPython. These are reference/source checks, not execution of RustPython. Existing tests/Lib files, assertions, expected failures and workflows are unchanged.

Final threaded cargo check passed in 1m09s and all-targets Clippy in 2m27s. All 12 unchanged baseline diagnostics match exactly; no warnings were suppressed. Ordinary commit hooks passed. Native RustPython was not run because the required execution guard has not been verified. Full workspace/C-API suites, native runtime differential tests and separate platform/feature graphs remain unrun; hosted CI is pending.

The initializer follow-up is independently reviewed against an additional 49-check CPython oracle, of which 23 checkpoints cover selected controls and negative controls; the remaining checkpoints document excluded behaviors. An additional independent initializer oracle passed 83 checkpoints covering reentrant initialization, ownership survival, failure state, keyword order and metadata. Final follow-up source review, compilation, Clippy and ordinary commit hooks passed.

Limits and integration

Generic tuple conversion's allocation-boundary failure cleanup, tuple/structseq teardown, and caller-wide argument destruction are not solved by this group. ExceptionGroup conversion/repr behavior and SystemExit empty-reinitialization code retention were the three deliberately excluded controls in the original oracle; the initializer follow-up now fixes the SystemExit case. Specialized native layouts and OSError's specialized reduction are unchanged. The existing PyAtomicRef deferred reclamation remains necessary for borrow safety, so immediate CPython field-finalizer timing is not claimed. Shared ArgSpec typo suggestions/surrogate diagnostics remain outside this initializer follow-up; the unmerged #9718 parser changes are not duplicated. SyntaxError initializer changes overlap #8348 and are excluded. ExceptionGroup work remains in #9588 rather than being duplicated here.

The shared Constructor change is limited to BASE_EXC_SUBCLASS and retains the existing checked payload/type allocation path. It prevents freshly constructed specialized exceptions from acquiring an observable empty state dictionary merely as an allocation side effect.

Examined peers for reporting, native layouts, GC, SyntaxError storage and ExceptionGroup derivation do not implement these contracts. Their eventual textual composition must preserve each independent behavior. Public fallible exception formatting and the new tuple helper affect Rust integration; in-tree call sites were updated, while internal forgiving reporting remains separate.

AI-assisted contribution by OpenAI Codex; assistance is disclosed in the commit trailer.

@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Caution

Review failed

The pull request is closed.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Preserve lazy dictionaries and reduction identity, propagate public formatting errors, honor dynamic state and note protocols, and share borrowed tuple conversion while retaining internal diagnostic behavior.

Assisted-by: OpenAI Codex:model version not exposed
Share raw argument installation and keyword validation while retaining original owners across reentrant cleanup.

Assisted-by: OpenAI Codex:model version not exposed
@youknowdot
youknowdot force-pushed the fix/exception-state-controls-20261104 branch from 2bd4bef to 443306b Compare November 5, 2026 14:51
Comment thread crates/vm/src/exceptions.rs Outdated
Comment on lines +864 to +865
#[pymethod(name = "add_note")]
fn add_note_object(&self, note: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

keep this fn name to add_note to avoid to overrride name. give another name to current pub fn add_note

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 244b7bf: the Python wrapper is now add_note with plain #[pymethod], and the typed Rust helper is add_note_str. Updated all Rust callers. Focused VM/stdlib Clippy, formatting, and commit hooks pass.

Rename the typed Rust helper to add_note_str and update its callers so the Python wrapper needs no name override.

Assisted-by: OpenAI Codex:model version not exposed
@codspeed

codspeed Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 62 untouched benchmarks
⏩ 4 skipped benchmarks1


Comparing youknowdot:fix/exception-state-controls-20261104 (244b7bf) with main (2dbcd89)2

Open in CodSpeed

Footnotes

  1. 4 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. No successful run was found on main (5a58ad2) during the generation of this report, so 2dbcd89 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@youknowone
youknowone marked this pull request as ready for review November 6, 2026 11:39
@chatgpt-codex-connector

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ❌ Failed 2026-11-06T11:39:29.117981Z
We couldn’t complete this review. Comment @codex review to try again.
244b7bf Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@youknowone
youknowone merged commit e93745f into RustPython:main Nov 6, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants