Skip to content

eval/importing parity: IMPORT_STAR sync, SETUP_ANNOTATIONS probe, IMPORT_NAME __import__ - #470

Merged
youknowone merged 3 commits into
mainfrom
box-pool
Jul 10, 2026
Merged

eval/importing parity: IMPORT_STAR sync, SETUP_ANNOTATIONS probe, IMPORT_NAME __import__#470
youknowone merged 3 commits into
mainfrom
box-pool

Conversation

@youknowone

@youknowone youknowone commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Two follow-up slices from the same sub-agent batch as #465.

eval: IMPORT_STAR dictscope sync, annotations item probe

Ports two pyopcode.py shapes in pyre-interpreter/src/eval.rs:

  • IMPORT_STAR fetched the locals mapping via get_or_create_w_locals, skipping both the fast2locals pre-sync and the locals2fast writeback. Now follows pyopcode.py IMPORT_STAR: getdictscope()import_all_from_wsetdictscope(w_locals), so the mapping reflects live fast locals before the merge and the merged names are written back into the frame's fast locals.
  • SETUP_ANNOTATIONS probed for __annotations__ with a membership check (contains); pyopcode.py uses finditem_str item lookup, which a custom mapping's __contains__ can disagree with. The store keeps setitem with a w_str_new key since pyre has no setitem_str.

Parity spot checks (pyre vs CPython, identical output/exit): from module import * with local writeback, and class-level annotations including re-annotation.

gc: cite upstream write-barrier decision points

Comment-only: the hand-run write barriers (function_write_barrier, Object-strategy list barrier) now cite the GC-transform insertions they stand in for (minimark.py write_barrier, rgc.py ll_writebarrier); pyre has no transform pass, so callers run them by hand.

Verification

  • cargo test -p pyre-interpreter --features dynasm --lib — 375 passed, 0 failed
  • python ./pyre/check.py --backend cranelift — 161/161 ALL PASSED
  • python ./pyre/check.py --backend dynasm — 160/161: the one failure is the nested_loop perf-ratio gate (0.47s vs pypy 0.22s, stable across direct reruns), pre-existing on the current main base: nested_loop.py contains no import * / annotations, so this diff's opcode bodies never execute there. It first appears with the base advance that brought in jit-regalloc: retire walker-slot cross-slot coalesce filter for pcdep-sourced interference (#371) #424 (dynasm regalloc walker-slot coalesce filter retirement); cranelift is unaffected. Worth a separate look.

importing: IMPORT_NAME calls builtins import

Found while verifying the above: IMPORT_NAME ignored a monkeypatched builtins.__import__ and always performed a real import (extra_tests/snippets/import.py failed its __import__-override assertions). Ported the pyopcode.py IMPORT_NAME shape into importing::import_name — fetch __import__ from the frame's builtins (ImportError "__import__ not found" when missing), w_locals from the frame debug slot or None, call it with (w_modulename, w_globals, w_locals, w_fromlist, w_flag). Both the eval-loop opcode and the JIT residual bh_import_name_fn route through the helper. With this commit the full gate is green on both backends: dynasm 161/161, cranelift 161/161 (including nested_loop, confirming the earlier perf-gate failure was borderline load sensitivity).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of module imports, including import levels, from-lists, and custom import hooks.
    • Fixed wildcard imports so imported names are correctly reflected in the current local scope.
    • Improved creation of __annotations__ for custom local mappings, ensuring consistent lookup behavior.
  • Documentation
    • Clarified internal memory-management behavior for improved maintainability.

IMPORT_STAR fetched the locals mapping via get_or_create_w_locals,
skipping both the fast2locals pre-sync and the locals2fast writeback.
Port the pyopcode.py IMPORT_STAR shape: getdictscope() before
import_all_from_w, setdictscope() after.

SETUP_ANNOTATIONS probed for __annotations__ with a membership check;
pyopcode.py uses finditem_str item lookup, which a custom mapping's
__contains__ can disagree with. The store keeps setitem with a
w_str_new key since pyre has no setitem_str.

Assisted-by: Claude
Comment-only: the hand-run write barriers in function_write_barrier
and the Object-strategy list barrier now cite the GC-transform
insertions they stand in for (minimark.py write_barrier, rgc.py
ll_writebarrier); pyre has no transform pass, so callers run them
by hand.

Assisted-by: Claude
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Import-name handling is centralized through a frame-aware helper used by interpreter and JIT paths. Annotation and star-import locals handling is adjusted, while function and list write-barrier documentation is expanded.

Changes

Import and locals execution

Layer / File(s) Summary
Frame-aware import dispatch
pyre/pyre-interpreter/src/importing.rs, pyre/pyre-interpreter/src/eval.rs, pyre/pyre-jit/src/call_jit.rs
IMPORT_NAME paths now call a shared frame-aware helper that resolves builtins, derives locals, invokes __import__, and returns the module object.
Annotation and star-import locals synchronization
pyre/pyre-interpreter/src/eval.rs
Annotation setup uses lookup semantics, while star imports update the frame dict scope and write it back to fast locals.

Write-barrier documentation

Layer / File(s) Summary
Manual write-barrier documentation
pyre/pyre-interpreter/src/function.rs, pyre/pyre-object/src/listobject.rs
Comments document manual barriers for function field stores and list block/reference updates.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • youknowone/pyre#318: Both changes concern the list_write_barrier residual-call path and its ABI or call-site behavior.

Sequence Diagram(s)

sequenceDiagram
  participant PyFrame
  participant import_name
  participant BuiltinImport
  PyFrame->>import_name: provide import name, fromlist, and flag
  import_name->>PyFrame: resolve builtins and frame locals
  import_name->>BuiltinImport: invoke __import__
  BuiltinImport-->>import_name: return module
  import_name-->>PyFrame: push imported module
Loading

Poem

A rabbit hops through imports bright,
Frame-held paths now guide the flight.
Annotations bloom, locals align,
Barriers guard each stored design.
“Sniff!” says the hare, “the code is fine!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main interpreter import and annotation behavior changes in the PR.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch box-pool

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

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit 970958f).

1. Regressions to PyPy parity introduced by this patch

  • pyre/pyre-interpreter/src/importing.rs:1871 ↔ pypy/interpreter/pyopcode.py:1116: Rust reads frame.w_builtin directly; PyPy calls self.get_builtin(). A frame with an unset cached builtin but a valid execution-context default now raises ImportError("__import__ not found"); before this patch it could still use importhook.

  • pyre/pyre-jit/src/call_jit.rs:4133 ↔ pypy/interpreter/pyopcode.py:1110: on a null residual frame, Rust returns 0 without publishing an exception. The subsequent GUARD_NO_EXCEPTION can therefore accept a null “module”; the interpreter path always performs IMPORT_NAME or raises.

2. Other mismatches introduced by this patch

None.

3. Pre-existing mismatches (already present before this patch)

None.

4. Structural adaptations

  • pyre/pyre-interpreter/src/function.rs:157 ↔ rpython/memory/gctransform/framework.py:1423: Rust explicitly invokes try_gc_write_barrier after function-field stores, whereas RPython’s GC transformation inserts the barrier after translated pointer stores. This is a necessary Rust/GC-pipeline adaptation.

  • pyre/pyre-object/src/listobject.rs:465 ↔ rpython/rlib/rgc.py:1196: Rust manually barriers both the custom-traced list and, when GC-managed, its items block; RPython uses transformed ll_writebarrier support for custom tracers. This is a necessary Rust moving-GC adaptation.

IMPORT_NAME resolved modules by calling importhook directly, so a
monkeypatched builtins.__import__ was ignored. Port the pyopcode.py
IMPORT_NAME shape into importing::import_name: fetch __import__ from
the frame's builtins (ImportError "__import__ not found" when
missing), take w_locals from the frame debug slot or None, and call
it with (w_modulename, w_globals, w_locals, w_fromlist, w_flag).

The eval-loop opcode and the JIT residual bh_import_name_fn both
route through the new helper; the residual's level operand is passed
through as the flag object instead of being unboxed to an int.

extra_tests/snippets/import.py now passes its __import__-override
assertions.

Assisted-by: Codex
Assisted-by: Claude
@youknowone youknowone changed the title eval: IMPORT_STAR dictscope sync, SETUP_ANNOTATIONS item probe; GC barrier citations eval/importing parity: IMPORT_STAR sync, SETUP_ANNOTATIONS probe, IMPORT_NAME __import__ Jul 10, 2026
@youknowone
youknowone merged commit efcda1c into main Jul 10, 2026
29 checks passed
@youknowone
youknowone deleted the box-pool branch July 10, 2026 22:54
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.

1 participant