Bytecode parity - boolop, comprehension, CFG passes#7631
Conversation
📝 WalkthroughWalkthroughRefactors comprehension inlining and symbol merging, adds a hidden-locals overlay and overlay-aware locals APIs to frames, and rewrites bytecode dump tooling to write JSON to files with timeout-aware subprocess retry and per-target reruns. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller
participant Frame
participant VM
participant Overlay
Caller->>Frame: write_local(name, value)
Frame->>Frame: has_active_hidden_locals()?
alt hidden locals active
Frame->>Overlay: ensure/init overlay mapping (f_locals_hidden_overlay)
Frame->>Overlay: write name→value
Frame->>VM: mark locals_dirty = true
else no hidden locals
Frame->>VM: sync_visible_locals_to_mapping(name, value)
VM->>VM: update backing mapping
end
Caller->>Frame: locals() request
Frame->>Frame: has_active_hidden_locals()?
alt hidden locals active
Frame->>Overlay: return fresh snapshot from overlay (merged)
else
Frame->>VM: return backing mapping snapshot
end
sequenceDiagram
participant Controller
participant Worker as dis_dump subprocess
participant FS as OutputFile
Controller->>Worker: start dump job (--output OutputFile)
Worker->>FS: write JSON results (or empty/partial)
Controller->>Worker: wait for completion (with DUMP_TIMEOUT)
alt timeout or unreadable JSON
Controller->>Controller: _run_sync_dump / _rerun_missing_targets (serial)
Controller->>Worker: start per-target subprocess invocations (serial)
Worker->>FS: write per-target JSON (or error)
end
Controller->>FS: _load_dump_output(output_file) -> parse / merge results
Controller->>Controller: merge recovered results into final report
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Sorry, something went wrong.
2e4339e to
d8ac86b
Compare
April 19, 2026 13:57
- Flatten nested same-op BoolOp and add IfExpr to jump_if - Simplify is_name_imported to module-level only - Enable inlined comprehensions in module/class scope - Add TweakInlinedComprehensionScopes with fast_hidden tracking - Track fb_range in FBlockInfo for with-statement line info - Add constant subscript folding and unary Not folding - Add emit_return_const_no_location for implicit returns - Use JumpNoInterrupt for ternary/except jumps - Add STACK_USE_GUIDELINE threshold for collection building - Reorder CFG pipeline: inline small blocks earlier, resolve line numbers before cold block extraction - Add redirect_empty_unconditional_jump_targets, reorder_conditional_chain_and_jump_back_blocks, materialize_empty_conditional_exit_targets, duplicate_shared_jump_back_targets passes - Add borrow deoptimization for multi-handler, named-except, protected conditional tail, and protected import joins - Run folding/optimization passes twice around peephole
8debf0b to
7367e26
Compare
April 20, 2026 11:09
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: (module 'code test_compile test_inspect test_json test_peepholer' not found) Legend:
|
Sorry, something went wrong.
- Augmented assignment with two-part slices uses BINARY_SLICE/STORE_SLICE - Inline async comprehensions (remove await/async guards) - Inlined comprehension cleanup jump uses JumpNoInterrupt - Class firstlineno uses first decorator line when decorated - Recurse into nested functions for static attribute collection - Fold unary positive complex constants (+0.0j) - Add deoptimize_borrow_for_folded_nonliteral_exprs pass - Add inline_single_predecessor_artificial_expr_exit_blocks pass - Skip shared artificial expr-stmt exit blocks in small-block inlining - Mark folded boolop tail as folded_from_nonliteral_expr
7367e26 to
f4674b6
Compare
April 20, 2026 12:02
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/vm/src/frame.rs (1)
918-1022: ⚠️ Potential issue | 🟠 MajorPreserve
f_localswrite-back semantics when returning an overlay.Line 923 creates a detached dict and Lines 1018-1020 return it without storing it on the frame.
frame.f_localscallers can mutate that dict, butlocals_to_fast()later reads fromself.locals.mapping(vm), so those mutations are silently lost while hidden locals are active. Consider either routing onlylocals()snapshot behavior through this overlay path, or storing/merging the overlay sof_localschanges can be synced back before resume.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/vm/src/frame.rs` around lines 918 - 1022, The overlay dict created in overlay_locals is returned as ArgMapping::from_dict_exact without being stored on the frame, so mutations to frame.f_locals are lost when locals_to_fast() later reads self.locals.mapping(vm); update the code in the locals-to-ArgMapping path (the block using overlay_locals and returning ArgMapping::from_dict_exact) to either persist the overlay on the frame (e.g., assign it to a frame field like self.overlay_locals or self.f_locals_overlay) so future locals_to_fast() can sync it back, or merge any mutations from the overlay into the frame’s underlying locals mapping before returning (so locals_to_fast() will see them); ensure related symbols touched are overlay_locals, ArgMapping::from_dict_exact, frame.f_locals (or self.locals), and locals_to_fast().scripts/compare_bytecode.py (1)
75-113: ⚠️ Potential issue | 🟡 MinorClose temp files in exception handler before unlinking to avoid Windows
PermissionError.If an exception occurs between the
NamedTemporaryFilecreations and theirclose()calls (e.g., duringfiles_file.write()on line 21), both files remain open. The exception handler then callsos.unlink()on the open files, which raisesPermissionErroron Windows and masks the original exception. Close both handles in the except block before unlinking, or use context managers to ensure files are closed.While the script is currently Linux-only in CI workflows, this is worth fixing for general robustness.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/compare_bytecode.py` around lines 75 - 113, The exception handler currently unlinks files_file and output_file while they may still be open, which causes PermissionError on Windows; update the except block in the function that creates output_file/files_file so it first checks for and closes both handles (files_file.close() and output_file.close()) if they exist/open (guard via locals() or try/except), then call os.unlink() for each path, and finally re-raise the original exception; alternatively wrap the temp file logic in context managers but ensure the same variables (files_file, output_file) are closed before unlinking to avoid masking the original error.
🧹 Nitpick comments (4)
scripts/dis_dump.py (1)
395-400: Minor: considercontextlib.ExitStackor a small helper for cleaner stdout/file fallback.The current try/finally is correct, but the two-branch
if args.outputon lines 395 and 399 can be consolidated usingcontextlib.nullcontext(sys.stdout)so that thewithsemantics handle closing uniformly.♻️ Proposed refactor
- output = open(args.output, "w", encoding="utf-8") if args.output else sys.stdout - try: - json.dump(results, output, ensure_ascii=False, separators=(",", ":")) - finally: - if args.output: - output.close() + import contextlib + output_cm = ( + open(args.output, "w", encoding="utf-8") + if args.output + else contextlib.nullcontext(sys.stdout) + ) + with output_cm as output: + json.dump(results, output, ensure_ascii=False, separators=(",", ":"))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/dis_dump.py` around lines 395 - 400, Replace the try/finally file-handle pattern around json.dump with a context manager that unifies stdout and file handling: use contextlib.nullcontext(sys.stdout) (or contextlib.ExitStack) to open args.output when present and yield sys.stdout otherwise, then perform json.dump(results, output, ...) inside a single with block; reference the variables/functions output, args.output, and json.dump to locate and modify the existing block.scripts/compare_bytecode.py (1)
194-199:stdoutreferenced vialocals()after a timeout path that never sets it.On the timeout branch (lines 179–186)
data = Noneis assigned butstdoutis not, hence the"stdout" in locals()guard on line 197. This works, but the flow is fragile — any refactor that adds another exception path will need to remember this invariant. A plainstdout = b""at the top of the function (mirroring the pattern in_run_sync_dump) would eliminate thelocals()check and make the intent explicit.♻️ Suggested tidy
def _finish_one(job): """Wait for a single dis_dump.py process and return parsed JSON.""" proc = job["proc"] expected = {relpath for relpath, _ in job["targets"]} + stdout = b"" try: stdout = proc.communicate(timeout=600)[0] except subprocess.TimeoutExpired: ... data = None else: data = _load_dump_output(job["output_file"]) finally: ... - stray = stdout.decode(errors="replace").strip() if "stdout" in locals() else "" + stray = stdout.decode(errors="replace").strip()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/compare_bytecode.py` around lines 194 - 199, The function currently uses "stdout" only in some branches and guards it with '"stdout" in locals()' which is fragile; initialize stdout = b"" at the top of the function (same pattern as _run_sync_dump) so stdout is always defined, remove the locals() check and simply decode stdout (e.g. stray = stdout.decode(errors="replace").strip()) and check if stray to emit the warning; update references in the timeout/error handling in this function accordingly (keep the proc.returncode check and stray warning logic) so no code paths leave stdout undefined.crates/codegen/src/symboltable.rs (2)
2227-2237: Minor: comment narrower than the actual gate.The comment states the exclusion is for "annotation scopes nested in classes that can see class scope", but the check is
parent_can_see_class_scope, which is also set onTypeParamsscopes inside a class (seeenter_type_param_block, line 1079) and onscan_type_param_bound_or_defaultscopes. So generic-class type-parameter scopes and TypeVar bound/default scopes nested in a class will also skip inlining. If that is intentional (it matches CPython), consider broadening the comment to avoid future confusion.📝 Suggested wording
// PEP 709: Mark non-generator comprehensions for inlining. - // CPython's symtable marks all non-generator comprehensions for - // inlining, except annotation scopes nested in classes that can see - // class scope. + // CPython's symtable marks all non-generator comprehensions for + // inlining, except when the enclosing scope can see class scope + // (annotation, type-parameter, and TypeVar bound/default scopes + // nested in a class).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/codegen/src/symboltable.rs` around lines 2227 - 2237, The comment is too narrow: the gate checking parent_can_see_class_scope (used with is_generator) also applies to TypeParams and type-var bound/default scopes (see enter_type_param_block and scan_type_param_bound_or_default), so update the comment above the inlining logic to state that any nested annotation-like scopes that can see class scope (including generic-class type-parameter scopes and TypeVar bound/default scopes) are excluded from comp_inlined rather than only “annotation scopes nested in classes that can see class scope”; leave the logic using parent_can_see_class_scope, is_generator, and setting comp_inlined unchanged.
570-607: Optional: fuse the two post-analysis passes oversymbol_table.symbols.The pass at 572-576 must run before
analyze_symbol(line 579) so that theUnknown+COMP_CELLbranch at 689-701 sees the flag. That's fine. However, the third pass at 600-607 (LOCAL→CELL promotion) can be folded into theanalyze_symbolloop at 579-586 since its decision depends only on the just-resolvedsymbol.scope,inlined_cells, andpromote_inlined_cells_to_cell(which is constant per call). This also lets the free-var collection at 583-585 see the promotedCellscope in one pass, which may matter if a future change relies on Cell symbols appearing innewfreeconsistently.♻️ Sketch
- for symbol in symbol_table.symbols.values_mut() { - if inlined_cells.contains(&symbol.name) { - symbol.flags.insert(SymbolFlags::COMP_CELL); - } - } - - // Analyze symbols in current scope - for symbol in symbol_table.symbols.values_mut() { - self.analyze_symbol(symbol, symbol_table.typ, sub_tables, class_entry)?; - - // Collect free variables from this scope - if symbol.scope == SymbolScope::Free || symbol.flags.contains(SymbolFlags::FREE_CLASS) { - newfree.insert(symbol.name.clone()); - } - } - - // PEP 709 / CPython symtable.c: - // - only promote LOCAL -> CELL in function-like scopes, where - // analyze_cells() runs. Module and class scopes keep their normal - // scope and rely on DEF_COMP_CELL for comprehension-only cells. - let promote_inlined_cells_to_cell = matches!( + for symbol in symbol_table.symbols.values_mut() { + if inlined_cells.contains(&symbol.name) { + symbol.flags.insert(SymbolFlags::COMP_CELL); + } + } + + // PEP 709 / CPython symtable.c: only promote LOCAL -> CELL in + // function-like scopes where analyze_cells() runs. + let promote_inlined_cells_to_cell = matches!( symbol_table.typ, CompilerScope::Function | CompilerScope::AsyncFunction | CompilerScope::Lambda | CompilerScope::Comprehension | CompilerScope::Annotation ); - for symbol in symbol_table.symbols.values_mut() { - if inlined_cells.contains(&symbol.name) - && promote_inlined_cells_to_cell - && symbol.scope == SymbolScope::Local - { - symbol.scope = SymbolScope::Cell; - } - } + for symbol in symbol_table.symbols.values_mut() { + self.analyze_symbol(symbol, symbol_table.typ, sub_tables, class_entry)?; + + if promote_inlined_cells_to_cell + && symbol.scope == SymbolScope::Local + && inlined_cells.contains(&symbol.name) + { + symbol.scope = SymbolScope::Cell; + } + + if symbol.scope == SymbolScope::Free || symbol.flags.contains(SymbolFlags::FREE_CLASS) { + newfree.insert(symbol.name.clone()); + } + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/codegen/src/symboltable.rs` around lines 570 - 607, The third pass that promotes LOCAL→CELL based on inlined_cells and promote_inlined_cells_to_cell should be folded into the loop that calls self.analyze_symbol so you only iterate symbol_table.symbols once; after calling self.analyze_symbol(symbol, ...), compute promote_inlined_cells_to_cell (as already defined) and if inlined_cells.contains(&symbol.name) && promote_inlined_cells_to_cell && symbol.scope == SymbolScope::Local then set symbol.scope = SymbolScope::Cell before you collect free vars into newfree, ensuring the COMP_CELL bit-setting pass (which must run first) remains unchanged and newfree sees the promoted scope in the same pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/compare_bytecode.py`:
- Around line 164-170: _rerun_missing_targets currently treats a falsy return
from _run_sync_dump the same (dropping both {} and None), losing persistent
read/parse failures from _load_dump_output; change _rerun_missing_targets to
explicitly check for None vs empty dict after calling _run_sync_dump (use
identity or explicit is None check), and when data is None insert a synthetic
error entry for that target (e.g. a dict value indicating a parse/read failure)
into the recovered mapping so downstream accounting in main() (cp_err/rp_err and
cp_data/rp_data) will count/report the error; keep successful {} and non-empty
dict returns unchanged.
- Around line 133-161: The _run_sync_dump function currently ignores its timeout
parameter and uses a fragile locals() trick for timed_out; update
proc.communicate(...) to use the function parameter
(proc.communicate(timeout=timeout)) and initialize timed_out = False before the
try/except so you can set timed_out = True in the except handler and drop the
locals() lookup in the finally. Also mirror this change in the similar helper
_finish_one so the timeout value is respected consistently across both helpers.
---
Outside diff comments:
In `@crates/vm/src/frame.rs`:
- Around line 918-1022: The overlay dict created in overlay_locals is returned
as ArgMapping::from_dict_exact without being stored on the frame, so mutations
to frame.f_locals are lost when locals_to_fast() later reads
self.locals.mapping(vm); update the code in the locals-to-ArgMapping path (the
block using overlay_locals and returning ArgMapping::from_dict_exact) to either
persist the overlay on the frame (e.g., assign it to a frame field like
self.overlay_locals or self.f_locals_overlay) so future locals_to_fast() can
sync it back, or merge any mutations from the overlay into the frame’s
underlying locals mapping before returning (so locals_to_fast() will see them);
ensure related symbols touched are overlay_locals, ArgMapping::from_dict_exact,
frame.f_locals (or self.locals), and locals_to_fast().
In `@scripts/compare_bytecode.py`:
- Around line 75-113: The exception handler currently unlinks files_file and
output_file while they may still be open, which causes PermissionError on
Windows; update the except block in the function that creates
output_file/files_file so it first checks for and closes both handles
(files_file.close() and output_file.close()) if they exist/open (guard via
locals() or try/except), then call os.unlink() for each path, and finally
re-raise the original exception; alternatively wrap the temp file logic in
context managers but ensure the same variables (files_file, output_file) are
closed before unlinking to avoid masking the original error.
---
Nitpick comments:
In `@crates/codegen/src/symboltable.rs`:
- Around line 2227-2237: The comment is too narrow: the gate checking
parent_can_see_class_scope (used with is_generator) also applies to TypeParams
and type-var bound/default scopes (see enter_type_param_block and
scan_type_param_bound_or_default), so update the comment above the inlining
logic to state that any nested annotation-like scopes that can see class scope
(including generic-class type-parameter scopes and TypeVar bound/default scopes)
are excluded from comp_inlined rather than only “annotation scopes nested in
classes that can see class scope”; leave the logic using
parent_can_see_class_scope, is_generator, and setting comp_inlined unchanged.
- Around line 570-607: The third pass that promotes LOCAL→CELL based on
inlined_cells and promote_inlined_cells_to_cell should be folded into the loop
that calls self.analyze_symbol so you only iterate symbol_table.symbols once;
after calling self.analyze_symbol(symbol, ...), compute
promote_inlined_cells_to_cell (as already defined) and if
inlined_cells.contains(&symbol.name) && promote_inlined_cells_to_cell &&
symbol.scope == SymbolScope::Local then set symbol.scope = SymbolScope::Cell
before you collect free vars into newfree, ensuring the COMP_CELL bit-setting
pass (which must run first) remains unchanged and newfree sees the promoted
scope in the same pass.
In `@scripts/compare_bytecode.py`:
- Around line 194-199: The function currently uses "stdout" only in some
branches and guards it with '"stdout" in locals()' which is fragile; initialize
stdout = b"" at the top of the function (same pattern as _run_sync_dump) so
stdout is always defined, remove the locals() check and simply decode stdout
(e.g. stray = stdout.decode(errors="replace").strip()) and check if stray to
emit the warning; update references in the timeout/error handling in this
function accordingly (keep the proc.returncode check and stray warning logic) so
no code paths leave stdout undefined.
In `@scripts/dis_dump.py`:
- Around line 395-400: Replace the try/finally file-handle pattern around
json.dump with a context manager that unifies stdout and file handling: use
contextlib.nullcontext(sys.stdout) (or contextlib.ExitStack) to open args.output
when present and yield sys.stdout otherwise, then perform json.dump(results,
output, ...) inside a single with block; reference the variables/functions
output, args.output, and json.dump to locate and modify the existing block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 5b61ad95-98d4-40ae-b77d-a2a1ae6a06ce
⛔ Files ignored due to path filters (6)
Lib/test/test_code.pyis excluded by!Lib/**Lib/test/test_compile.pyis excluded by!Lib/**Lib/test/test_inspect/test_inspect.pyis excluded by!Lib/**Lib/test/test_peepholer.pyis excluded by!Lib/**crates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_bool_op.snapis excluded by!**/*.snapcrates/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snapis excluded by!**/*.snap
📒 Files selected for processing (7)
crates/codegen/src/compile.rscrates/codegen/src/ir.rscrates/codegen/src/symboltable.rscrates/compiler-core/src/marshal.rscrates/vm/src/frame.rsscripts/compare_bytecode.pyscripts/dis_dump.py
Sorry, something went wrong.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
scripts/compare_bytecode.py (1)
172-196: ⚠️ Potential issue | 🟡 MinorPreserve failed reruns in the result map.
failed/emptytargets are only logged, then omitted fromrecovered. If both interpreters lose the same target, the final report can under-count it instead of reporting an error.Suggested fix
def _rerun_missing_targets(interpreter, targets, base_dir): recovered = {} failed = [] empty = [] for target in targets: + relpath = target[0] data = _run_sync_dump(interpreter, [target], base_dir) if data is None: - failed.append(target[0]) + failed.append(relpath) + recovered[relpath] = { + "status": "error", + "error": "dump helper failed while rerunning target", + } elif data: recovered.update(data) else: - empty.append(target[0]) + empty.append(relpath) + recovered[relpath] = { + "status": "error", + "error": "dump helper produced no data while rerunning target", + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/compare_bytecode.py` around lines 172 - 196, The _rerun_missing_targets function currently logs failed/empty targets but omits them from the returned recovered map, causing under-reporting; after computing failed and empty (use the same keying as recovered, i.e. target[0]), add entries for each failed and empty target into recovered (e.g., recovered[failed_name] = None) before returning so the caller sees these missing items instead of silently dropping them; update _rerun_missing_targets to insert those sentinel entries after the warning prints and then return recovered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/vm/src/builtins/frame.rs`:
- Around line 704-706: The call to self.f_locals_hidden_overlay.lock().take()
returns an Option<PyDictRef> annotated #[must_use], so explicitly discard it to
avoid warnings; update the code to bind the result (e.g., let _ =
self.f_locals_hidden_overlay.lock().take()) just like the pattern used for
self.temporary_refs.lock().clear(), referencing the f_locals_hidden_overlay
field and its take() call to make the intent clear and silence the must_use
lint.
In `@crates/vm/src/frame.rs`:
- Around line 1027-1063: The snapshot dicts for hidden locals are being created
empty and only fastlocals are synced, which drops visible names from the backing
mapping; update f_locals_mapping and locals so when you create a new overlay
dict you first seed it with the backing locals mapping (self.locals) before
overlaying fastlocals. Concretely: in f_locals_mapping when overlay is None,
construct the new dict, copy entries from self.locals.mapping(vm) (or clone its
dict) into overlay_dict before storing it in f_locals_hidden_overlay, and in
locals() when building the fresh snapshot use vm.ctx.new_dict() then copy
self.locals.mapping(vm) entries into that dict before calling
sync_visible_locals_to_mapping; keep using
ArgMapping::from_dict_exact(overlay_dict) and then overlay the fastlocals as you
do now.
- Around line 874-883: The code takes a mutable slice via
(*self.iframe.get()).localsplus.fastlocals_mut() and then calls
has_active_hidden_locals() which accesses the same frame through UnsafeCell,
creating overlapping &mut/& accesses; move the computation of overlay_locals
(the has_active_hidden_locals() check, f_locals_hidden_overlay.lock().clone(),
ArgMapping::from_dict_exact, and locals_map selection via ArgMapping::mapping or
self.locals.mapping(vm)) to occur before taking fastlocals_mut() so you only
borrow immutably/inspect the frame first and then obtain fastlocals_mut()
afterwards, ensuring no simultaneous mutable and shared access to
iframe/localsplus.
---
Duplicate comments:
In `@scripts/compare_bytecode.py`:
- Around line 172-196: The _rerun_missing_targets function currently logs
failed/empty targets but omits them from the returned recovered map, causing
under-reporting; after computing failed and empty (use the same keying as
recovered, i.e. target[0]), add entries for each failed and empty target into
recovered (e.g., recovered[failed_name] = None) before returning so the caller
sees these missing items instead of silently dropping them; update
_rerun_missing_targets to insert those sentinel entries after the warning prints
and then return recovered.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: c68aac22-f06b-45a0-81f4-59003ee1c1fe
📒 Files selected for processing (4)
crates/codegen/src/symboltable.rscrates/vm/src/builtins/frame.rscrates/vm/src/frame.rsscripts/compare_bytecode.py
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/codegen/src/symboltable.rs
Sorry, something went wrong.
aac855f to
a04edb1
Compare
April 20, 2026 14:24
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/compare_bytecode.py`:
- Around line 172-192: In _rerun_missing_targets, don't treat any non-empty
returned mapping as success; after calling _run_sync_dump and getting data,
verify that data contains the requested relpath (e.g., if relpath in data or
data.get(relpath) is not None) before calling recovered.update(data); if the
relpath key is missing then treat it like an empty/unexpected result (append
relpath to empty and set recovered[relpath] to the error message about no data),
otherwise merge the returned mapping into recovered and consider it recovered.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 37593bfe-688f-4991-9ed2-b6d49fd82976
📒 Files selected for processing (4)
crates/codegen/src/symboltable.rscrates/vm/src/builtins/frame.rscrates/vm/src/frame.rsscripts/compare_bytecode.py
🚧 Files skipped from review as they are similar to previous changes (2)
- crates/vm/src/builtins/frame.rs
- crates/vm/src/frame.rs
Sorry, something went wrong.
9140ef5
into
RustPython:main
Apr 20, 2026
Summary by CodeRabbit
Improvements
Development Tools