GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Align bytecode CFG cleanup with CPython by youknowone · Pull Request #7781 · RustPython/RustPython

Conversation

@youknowone

@youknowone youknowone commented May 5, 2026 •
edited by coderabbitai Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added a preprocessing pass that rewrites certain percent-format string expressions into f-string-style interpolations.
  • Bug Fixes

    • Improved control-flow, exception/cleanup sequencing, line-anchor/NOP preservation, constant-folding behavior, and boolean short-circuit/threading edge cases.
  • Tests

    • Added extensive CPython-style tests covering short-circuiting, loop backedge/continue cases, cleanup sequencing, parameter init, and bytecode layout.
  • Chores

    • Refactored scope/symbol analysis, layout-aware optimizations, jump-threading logic, and updated spell-check dictionary entries.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@coderabbitai

coderabbitai Bot commented May 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

One cohesive PR: add a percent-format AST preprocessor; restrict constant folding and pre-evaluate boolean prefixes; refactor try/with/f-string emission; add layout-aware IR NOP/layout helpers, short-circuit-aware jump threading, and a fast-scan path; unify symboltable scope handling; add tests and dictionary entries.

Changes

Codegen Control-Flow and IR Optimization Refactoring

Layer / File(s) Summary
Preprocess: percent-format -> f-string
crates/codegen/src/preprocess.rs, crates/codegen/src/lib.rs
Add preprocess_mod and AstPreprocessor to rewrite simple %-format expressions into Expr::FString with parsed interpolations and basic format-specs; register mod preprocess;.
Symbol Table Scope Unification
crates/codegen/src/symboltable.rs
Centralize scope-type determination via is_function_like_scope; pass explicit CompilerScope into enter_scope_with_parameters; track unevaluated annotations and extend named-expression scoping to match CPython.
Compile entry & constant folding
crates/codegen/src/compile.rs
Wire preprocess_mod into compile_top; restrict constant folding to expressions reported constant; ensure boolean-op prefix-values are compiled before short-circuit threading; add nested-with tail detection helper.
Try/Except end-path & With cleanup NOPs
crates/codegen/src/compile.rs
Refactor try normal-exit to route through a cleanup_block and directly compile orelse; compute preserve_outer_cleanup_target_nop from nested-with tail preservation and terminal suppress-exit predecessor detection to decide NOP retention.
F-string literal no-location tracking
crates/codegen/src/compile.rs
Thread pending_literal_no_location through f-string buffering/join paths and call set_no_location() when emitting marked pending literal fragments.
IR: Finalize & Peephole
crates/codegen/src/ir.rs
Replace exception-specific materialization with materialize_empty_conditional_exit_targets; convert peephole optimizer to indexed iteration and preserve pure self-loop block-start NOP anchors; update debug tracing.
IR: Layout-aware NOP Removal & Helpers
crates/codegen/src/ir.rs
Compute layout predecessors and add predicates (keep_target_start_no_location_nop, layout_predecessor_ends_with_pop_iter, is_async_loop_cleanup_block, block_has_simple_scope_exit, leading_bool_guard_has_scope_exit_successor) to drive NOP removal/retention and named-cleanup deopt logic.
IR: Jump Threading Short-Circuit Rules
crates/codegen/src/ir.rs
Add short_circuit_stub_conditional, opposite_short_circuit_target, and same_short_circuit_target and use them in jump_threading_impl to retarget conditional jumps for CPython-style boolean patterns; unit tests added.
IR: Fast-scan for Many Locals
crates/codegen/src/ir.rs
Add fast_scan_many_locals and route uninitialized-load checks through it when nlocals > 64, then clamp back to the smaller path’s supported range.
Tests / Validation
crates/codegen/src/compile.rs, crates/codegen/src/ir.rs
New tests for percent-format preprocess effects, fast-scan parameter initialization behavior, boolean short-circuit threading, loop header/backedge NOP ordering, return-in-loop cleanup sequencing, nested-with NOP retention/drop, and for-loop conditional-raise ordering.
Spell dictionary
.cspell.dict/cpython.txt
Add CPython-specific identifiers used in code/tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • RustPython/RustPython#7773: Overlapping edits to codegen/IR and symboltable scope handling.
  • RustPython/RustPython#7721: Related edits touching compile folding, try/with emission, and NOP/jump handling.
  • RustPython/RustPython#7541: Related changes around f-string lowering, constant folding, and control-flow emission.

Suggested reviewers

  • fanninpm

Poem

🐰 I hopped the AST with eager cheer,

turned percent signs to f-strings clear,
folded constants only when told,
threaded jumps and kept anchors bold,
tests clapped softly — off I steer.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Align bytecode CFG cleanup with CPython' is directly related to the main changes across multiple files that refactor and align bytecode control-flow-graph cleanup behavior with CPython standards.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
  • X
  • Mastodon
  • Reddit
  • LinkedIn

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

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@github-actions

github-actions Bot commented May 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[ ] lib: cpython/Lib/typing.py
[ ] test: cpython/Lib/test/test_typing.py (TODO: 3)
[x] test: cpython/Lib/test/test_type_aliases.py
[ ] test: cpython/Lib/test/test_type_annotations.py
[ ] test: cpython/Lib/test/test_type_params.py (TODO: 4)
[x] test: cpython/Lib/test/test_genericalias.py

dependencies:

  • typing (native: _typing, collections.abc, sys)
    • annotationlib (native: builtins, sys)
    • collections (native: _collections, _weakref, itertools, sys)
    • inspect (native: builtins, collections.abc, importlib.machinery, itertools, sys)
    • warnings (native: _contextvars, _thread, _warnings, builtins, sys)
    • abc, contextlib, copyreg, functools, operator, re, types

dependent tests: (17 tests)

  • typing: test_annotationlib test_builtin test_copy test_enum test_fractions test_funcattrs test_functools test_genericalias test_grammar test_inspect test_isinstance test_patma test_pydoc test_type_aliases test_type_params test_types test_typing

[x] test: cpython/Lib/test/test_compile.py (TODO: 16)
[x] test: cpython/Lib/test/test_compiler_assemble.py
[x] test: cpython/Lib/test/test_compiler_codegen.py
[ ] test: cpython/Lib/test/test_peepholer.py (TODO: 4)

dependencies:

dependent tests: (no tests depend on compile)

[x] test: cpython/Lib/test/test_positional_only_arg.py (TODO: 3)

dependencies:

dependent tests: (no tests depend on positional_only_arg)

[x] test: cpython/Lib/test/test_named_expressions.py (TODO: 11)

dependencies:

dependent tests: (no tests depend on named_expressions)

[x] test: cpython/Lib/test/test_with.py

dependencies:

dependent tests: (no tests depend on with)

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
youknowone marked this pull request as ready for review May 6, 2026 12:25
coderabbitai[bot]
coderabbitai Bot reviewed May 6, 2026
View reviewed changes

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/codegen/src/symboltable.rs (1)

1061-1070: 💤 Low value

Optional: document the contrast with compile.rs::is_function_like.

This is_function_like_scope (Function/AsyncFunction/Lambda/Comprehension/Annotation) intentionally differs from the is_function_like predicate in compile.rs (Function/AsyncFunction/Annotation/TypeParams). The set used here matches CPython's analyze_cells semantics in symtable.c, while the codegen variant guards CodeFlags. A short doc comment would help future readers avoid conflating them.

📝 Suggested doc comment
+    /// Scopes that participate in CPython's `analyze_cells` step (LOCAL→CELL
+    /// promotion and free-var removal). This intentionally differs from
+    /// `compile.rs::is_function_like`, which controls `CodeFlags` and uses a
+    /// different set (e.g. includes `TypeParams`, excludes `Lambda`/`Comprehension`).
     fn is_function_like_scope(typ: CompilerScope) -> bool {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/codegen/src/symboltable.rs` around lines 1061 - 1070, Add a short doc
comment above is_function_like_scope explaining that its set (Function,
AsyncFunction, Lambda, Comprehension, Annotation) intentionally differs from the
predicate compile.rs::is_function_like (which uses Function, AsyncFunction,
Annotation, TypeParams); note that is_function_like_scope mirrors CPython's
analyze_cells semantics in symtable.c while the compile.rs variant is used for
guarding CodeFlags, so readers should not conflate the two. Include references
to both symbols (is_function_like_scope and compile.rs::is_function_like) in the
comment for clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/codegen/src/ir.rs`:
- Around line 9229-9233: fast_scan_many_locals currently treats every local
index >=64 as unknown, causing parameters beyond index 63 to be misclassified;
pass the function's parameter count (nparams) into fast_scan_many_locals (or
otherwise make the helper aware of nparams) and mark any local index < nparams
as initialized/parameter so they are not converted to LOAD_FAST_CHECK or split
by LOAD_FAST_LOAD_FAST; update the call sites (and the fast path logic inside
fast_scan_many_locals and its use of merged_cell_local) to exempt indices <
nparams from the unknown high-index handling (also apply the same change to the
related code block around lines 9344-9402 that duplicates this fast path).
- Around line 10627-10672: The helpers opposite_short_circuit_target and
same_short_circuit_target must verify the entire short-circuit stub shape, not
just the first two ops and the trailing conditional jump; modify both functions
to (1) ensure the first instruction is exactly Instruction::Copy with
i.get(first.arg) == 1 and the second is exactly Instruction::ToBool, (2) iterate
over the instructions between index 2 and cond_idx (exclusive) and require each
instruction's real() to be either None or one of the allowed marker ops (e.g.
Instruction::Nop or Instruction::NotTaken) — reject the block if any other real
instruction appears, and (3) only then perform the existing matches against
block.instructions[cond_idx].instr.real(); apply the same stricter validation in
both opposite_short_circuit_target and same_short_circuit_target so
jump_threading_impl cannot skip real instructions when threading.

---

Nitpick comments:
In `@crates/codegen/src/symboltable.rs`:
- Around line 1061-1070: Add a short doc comment above is_function_like_scope
explaining that its set (Function, AsyncFunction, Lambda, Comprehension,
Annotation) intentionally differs from the predicate
compile.rs::is_function_like (which uses Function, AsyncFunction, Annotation,
TypeParams); note that is_function_like_scope mirrors CPython's analyze_cells
semantics in symtable.c while the compile.rs variant is used for guarding
CodeFlags, so readers should not conflate the two. Include references to both
symbols (is_function_like_scope and compile.rs::is_function_like) in the comment
for clarity.
🪄 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: ce25f7be-2b5c-4295-b7ae-f9c2f4a2465b

📥 Commits

Reviewing files that changed from the base of the PR and between d877c30 and 8189045.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_peepholer.py is excluded by !Lib/**
📒 Files selected for processing (3)
  • crates/codegen/src/compile.rs
  • crates/codegen/src/ir.rs
  • crates/codegen/src/symboltable.rs

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread crates/codegen/src/ir.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread crates/codegen/src/ir.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

coderabbitai[bot]
coderabbitai Bot reviewed May 7, 2026
View reviewed changes

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/codegen/src/ir.rs`:
- Around line 4648-4680: The current block_has_simple_scope_exit() treats
certain already-lowered fast-local superinstructions as non-simple and thus
causes leading_bool_guard_has_scope_exit_successor() to prematurely stop
segments; update the match arm that currently allows LoadFastLoadFast,
LoadFastBorrowLoadFastBorrow, etc., to also accept the lowered opcodes
StoreFastLoadFast, StoreFastStoreFast and LoadFastCheck (i.e., add
Instruction::StoreFastLoadFast { .. }, Instruction::StoreFastStoreFast { .. },
and Instruction::LoadFastCheck { .. } to the permissive Some(...) pattern) so
those successors are considered simple scope-exit blocks and the borrow deopt
path is not skipped.
- Around line 2655-2671: The check that sets
preserve_block_start_no_location_nop runs before the trailing conditional jump
is converted to an unconditional jump, so patterns like "LOAD_CONST True;
POP_JUMP_IF_TRUE <self>" are not recognized; move or re-run the
preserves_pure_self_loop_anchor detection after the jump-rewrite phase (i.e.,
after the code that turns the trailing conditional into a plain jump), or adjust
the predicate to treat the specific conditional that will be rewritten as
unconditional (use info.instr / info.instr.real() and is_unconditional_jump or
detect POP_JUMP_IF_TRUE with a constant true target) so that set_to_nop and the
preserves_pure_self_loop_anchor logic see the post-rewrite form before deciding
to set preserve_block_start_no_location_nop.
🪄 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: 6339f5f3-9b75-4593-a192-ec6e1323018f

📥 Commits

Reviewing files that changed from the base of the PR and between 8189045 and 597c759.

📒 Files selected for processing (2)
  • crates/codegen/src/compile.rs
  • crates/codegen/src/ir.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/codegen/src/compile.rs

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread crates/codegen/src/ir.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread crates/codegen/src/ir.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

coderabbitai[bot]
coderabbitai Bot reviewed May 7, 2026
View reviewed changes

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
crates/codegen/src/ir.rs (2)

4648-4663: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Treat already-lowered fast-local opcodes as simple scope exits.

This helper still rejects LoadFastCheck, StoreFastLoadFast, and StoreFastStoreFast, even though this pass runs after those opcodes can already exist. That makes leading_bool_guard_has_scope_exit_successor() stop on structurally simple cleanup successors and skip the intended borrow deopt.

Suggested fix
                     Some(
                         Instruction::Nop
                         | Instruction::NotTaken
                         | Instruction::LoadConst { .. }
                         | Instruction::LoadSmallInt { .. }
                         | Instruction::StoreFast { .. }
+                        | Instruction::StoreFastLoadFast { .. }
+                        | Instruction::StoreFastStoreFast { .. }
                         | Instruction::StoreName { .. }
                         | Instruction::LoadFast { .. }
                         | Instruction::LoadFastBorrow { .. }
+                        | Instruction::LoadFastCheck { .. }
                         | Instruction::LoadFastLoadFast { .. }
                         | Instruction::LoadFastBorrowLoadFastBorrow { .. }
                         | Instruction::BuildTuple { .. },
                     ) => {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/codegen/src/ir.rs` around lines 4648 - 4663, The helper
block_has_simple_scope_exit currently treats many opcodes as simple exits but
still rejects lowered fast-local opcodes; update the match in
block_has_simple_scope_exit (the loop over block.instructions) to also consider
LoadFastCheck, StoreFastLoadFast, and StoreFastStoreFast as simple scope exits
(i.e., include them in the same Some(Instruction::...) arm that returns true) so
that leading_bool_guard_has_scope_exit_successor will recognize structurally
simple cleanup successors after lowering; ensure you only add those opcode
variants to the existing accepted list and keep the early return behavior
unchanged.

2655-2679: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve the self-loop anchor after rewriting the conditional.

preserves_pure_self_loop_anchor is evaluated before Line 2673 rewrites POP_JUMP_* <self> into a plain jump. A block like LOAD_CONST True; POP_JUMP_IF_TRUE <self> still looks non-unconditional here, so the block-start NOP is not preserved and gets stripped later.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/codegen/src/ir.rs` around lines 2655 - 2679, The code computes
preserves_pure_self_loop_anchor before rewriting the conditional at
block.instructions[i+1], so POP_JUMP_IF_* <self> isn’t treated as unconditional
and the NOP gets dropped; fix by computing or re-checking the self-loop anchor
after the rewrite (i.e., move or recompute the preserves_pure_self_loop_anchor
logic to run after the branch that sets block.instructions[i+1] to an
unconditional Jump) and then set
block.instructions[i].preserve_block_start_no_location_nop = true when the
recalculated condition holds; reference set_to_nop,
preserves_pure_self_loop_anchor, block.instructions, and
preserve_block_start_no_location_nop.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/codegen/src/compile.rs`:
- Around line 611-619: The predicate statements_end_with_with_cleanup_scope_exit
only matches ast::Stmt::With and therefore misses nested async-with nodes;
update its match arm to handle ast::Stmt::AsyncWith (likely
ast::Stmt::AsyncWith(ast::StmtAsyncWith { body, .. })) the same way as
ast::Stmt::With so it recurses into async with bodies and calls
Self::statements_end_with_scope_exit and
Self::statements_end_with_with_cleanup_scope_exit for that body as well,
ensuring nested async with cleanup scopes are detected by
statements_end_with_with_cleanup_scope_exit and preventing
preserve_outer_cleanup_target_nop from dropping needed NOPs.
- Around line 19608-19616: The test function
test_loop_not_in_conditional_body_threads_true_path_to_jump_back currently uses
the expression "not k in 'bBhHiIlLfd'" which parses as unary not applied to the
in comparison; update the test string passed to compile_exec inside that
function to use the dedicated NotIn operator by replacing "not k in
'bBhHiIlLfd'" with "k not in 'bBhHiIlLfd'" so the test actually exercises the
NotIn code path (locate the test by the function name and the compile_exec call
with the multi-line string).

In `@crates/codegen/src/ir.rs`:
- Around line 4672-4681: The helper leading_bool_guard_has_scope_exit_successor
currently inspects block.next directly and can be misled by empty layout blocks;
change the successor check to skip empty placeholders by normalizing each
successor with next_nonempty_block(blocks, successor) before testing for scope
exits. In practice, in leading_bool_guard_has_scope_exit_successor (and while
using trailing_conditional_jump_index and block_has_simple_scope_exit), map both
block.instructions[cond_idx].target and block.next through
next_nonempty_block(blocks, ...) and then perform the NULL check and
block_has_simple_scope_exit check on the normalized successor.

---

Duplicate comments:
In `@crates/codegen/src/ir.rs`:
- Around line 4648-4663: The helper block_has_simple_scope_exit currently treats
many opcodes as simple exits but still rejects lowered fast-local opcodes;
update the match in block_has_simple_scope_exit (the loop over
block.instructions) to also consider LoadFastCheck, StoreFastLoadFast, and
StoreFastStoreFast as simple scope exits (i.e., include them in the same
Some(Instruction::...) arm that returns true) so that
leading_bool_guard_has_scope_exit_successor will recognize structurally simple
cleanup successors after lowering; ensure you only add those opcode variants to
the existing accepted list and keep the early return behavior unchanged.
- Around line 2655-2679: The code computes preserves_pure_self_loop_anchor
before rewriting the conditional at block.instructions[i+1], so POP_JUMP_IF_*
<self> isn’t treated as unconditional and the NOP gets dropped; fix by computing
or re-checking the self-loop anchor after the rewrite (i.e., move or recompute
the preserves_pure_self_loop_anchor logic to run after the branch that sets
block.instructions[i+1] to an unconditional Jump) and then set
block.instructions[i].preserve_block_start_no_location_nop = true when the
recalculated condition holds; reference set_to_nop,
preserves_pure_self_loop_anchor, block.instructions, and
preserve_block_start_no_location_nop.
🪄 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: b5a64a8f-10f8-467d-ac25-167695cc1990

📥 Commits

Reviewing files that changed from the base of the PR and between abf9495 and a8ba780.

📒 Files selected for processing (2)
  • crates/codegen/src/compile.rs
  • crates/codegen/src/ir.rs

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread crates/codegen/src/compile.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread crates/codegen/src/compile.rs
Comment on lines +19608 to +19616
#[test]
fn test_loop_not_in_conditional_body_threads_true_path_to_jump_back() {
let code = compile_exec(
"\
def f(native, array):
for k in native:
if not k in 'bBhHiIlLfd':
del array[k]
",

@coderabbitai coderabbitai Bot May 7, 2026

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Python's grammar/AST, how is not x in yparsed compared withx not in y? Does not x in ybecome unarynotapplied to anincomparison rather than thenot in comparison operator?

💡 Result:

In Python's grammar and AST, x not in y is parsed as a single comparison operator NotIn applied to x and y [1][2]. The grammar explicitly defines notin_bitwise_or: 'not' 'in' bitwise_or, producing a Compare node with NotIn operator in the AST [1][2]. In contrast, not x in y is parsed as the unary logical not applied to the Compare (x in y), because unary not has lower precedence than comparisons, and the grammar for not_test is 'not' not_test | comparison [3]. This produces a UnaryOp with Not operator whose operand is a Compare with In [4][5]. Thus, yes, not x in y becomes unary not applied to an in comparison, not the not in operator [6][7]. Both expressions evaluate equivalently (due to special casing or semantics), but their parse trees differ, and style guides prefer x not in y for clarity [8][9].

Citations:

  • 1: https://docs.python.org/3/reference/grammar.html
  • 2: https://github.com/python/cpython/blob/main/Grammar/python.gram
  • 3: https://docs.python.org/3.11/reference/expressions.html
  • 4: https://docs.python.org/3.15/library/ast.html
  • 5: http://docs.python.org/3/library/ast.html
  • 6: https://stackoverflow.com/questions/8738388/x-not-in-y-or-not-x-in-y
  • 7: https://stackoverflow.com/questions/2211706/are-not-in-and-is-not-both-operators-if-so-are-they-in-any-way-different-t
  • 8: https://fabiangunzinger.github.io/idiomatic-python/
  • 9: https://pycodestyle.pycqa.org/en/2.9.0/_modules/pycodestyle.html

Use k not in ... if this test is meant to cover NotIn.

The expression not k in 'bBhHiIlLfd' parses as unary not applied to the in comparison, not the dedicated NotIn operator. Since the test name indicates coverage of the NotIn path, use k not in 'bBhHiIlLfd' instead for accurate test coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/codegen/src/compile.rs` around lines 19608 - 19616, The test function
test_loop_not_in_conditional_body_threads_true_path_to_jump_back currently uses
the expression "not k in 'bBhHiIlLfd'" which parses as unary not applied to the
in comparison; update the test string passed to compile_exec inside that
function to use the dedicated NotIn operator by replacing "not k in
'bBhHiIlLfd'" with "k not in 'bBhHiIlLfd'" so the test actually exercises the
NotIn code path (locate the test by the function name and the compile_exec call
with the multi-line string).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread crates/codegen/src/ir.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
youknowone force-pushed the bytecode-parity branch 2 times, most recently from 6f0f259 to 5bb40c9 Compare May 9, 2026 15:12
@youknowone
youknowone marked this pull request as draft May 9, 2026 17:59
youknowone added 21 commits May 12, 2026 01:23
@youknowone
Align CFG cleanup bytecode with CPython
c09c475
@youknowone
remove test
fe64200
@youknowone
Align bytecode CFG cleanup with CPython
94e2ae3
@youknowone
fix
a743ffc
@youknowone
Align named-except borrow deopts with CPython
c998628
@youknowone
Remove duplicated Lib test codegen cases
68610b9
@youknowone
Cache CFG layout predecessors during NOP cleanup
c82c43f
@youknowone
Address bytecode parity review feedback
cd9a711
@youknowone
Align nested with cleanup bytecode
15a88df
@youknowone
Align conditional raise loop backedge ordering
4bd27be
@youknowone
Align percent format optimization with CPython preprocess
9b257b1
@youknowone
Preserve shared finally reraises in CFG cleanup
8fbe367
@youknowone
Align CFG cleanup with CPython finally layout
3ccda96
@youknowone
Align loop CFG anchors with CPython
2aa954f
@youknowone
Preserve loop false-path CFG bodies
742ff9b
@youknowone
Align protected store-subscript CFG bytecode
6cfa6f2
@youknowone
Align borrow deopts with CPython CFG
cc59c46
@youknowone
Align delete-loop CFG with CPython
891e972
@youknowone
Align CFG inlining with CPython jumps
19b7427
@youknowone
Align protected CFG jump threading
d734c06
@youknowone
Narrow handler resume borrow deopt
0e2b226
youknowone added 17 commits May 12, 2026 01:23
@youknowone
Align CFG cleanup and peephole parity
9c737eb
@youknowone
Align nested loop conditional CFG layout
d35c13d
@youknowone
Align named expression comprehension scope
bba340b
@youknowone
Align CFG cleanup with CPython line markers
ea757cf
@youknowone
Align CFG line marker cleanup with CPython
555e8fc
@youknowone
Align loop CFG fallthrough with CPython
8abe32a
@youknowone
Align conditional CFG fallthrough cases with CPython
05d96e4
@youknowone
Align protected CFG layout with CPython
a891818
@youknowone
Align CFG cleanup and type-param calls with CPython
24dde16
@youknowone
Align annotation and super call bytecode parity
93e8bc4
@youknowone
Align finally reraise tail inlining
1b414fe
@youknowone
Align protected loop CFG cleanup
7268983
@youknowone
Align loop CFG bytecode layout with CPython
a24a791
@youknowone
Align nested loop jump-back layout
0941b7a
@youknowone
Align conditional jump threading with CPython
448e1f2
@youknowone
fix
a448fb6
@youknowone
Skip test_stack_overflow under -u cpu
b3b8329
CFG cleanup passes exceed the 60-second worker timeout when compiling
200k chained if statements.
@youknowone
youknowone force-pushed the bytecode-parity branch from 5bb40c9 to b3b8329 Compare May 11, 2026 16:30
@youknowone
Fix CI lint and clippy errors
7790e54
Add cfws/CFWS/lslpp/nointerrupt/preds to cspell dictionary.
Replace .map(...).unwrap_or(-1) with .map_or(-1, ...) in ir.rs.
Drop expectedFailure on test_with.NestedWith.testExceptionLocation.
@youknowone
youknowone marked this pull request as ready for review May 12, 2026 02:48
youknowone
youknowone commented May 12, 2026
View reviewed changes
Comment thread Lib/test/test_compile.py Outdated
# bpo-31113: Stack overflow when compile a long sequence of
# complex statements.
@support.requires_resource('cpu')
@unittest.skip("TODO: RUSTPYTHON; CFG cleanup is too slow for 200k statements")

@youknowone youknowone May 12, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

must be investigated

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@youknowone

youknowone commented May 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

coderabbitai[bot] reacted with eyes emoji
All reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
Speed up CFG cleanup for large compile inputs
19bf583
@youknowone
youknowone merged commit 2b19ba7 into RustPython:main May 12, 2026
26 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
youknowone deleted the bytecode-parity branch May 12, 2026 13:14
This was referenced May 20, 2026
Align cleanup bytecode layout with CPython #7935
Merged
Align nested code object bytecode parity #7942
Merged
@coderabbitai coderabbitai Bot mentioned this pull request Jun 24, 2026
Update ruff to 0.15.19, use it from crates.io #8160
Draft
2 tasks
youknowone added a commit that referenced this pull request Sep 16, 2026
@youknowone
Align bytecode CFG cleanup with CPython (#7781)
edd7b4d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@coderabbitai coderabbitai[bot] coderabbitai[bot] left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@youknowone
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.