Bytecode parity: align borrow optimization with CFG traversal#7773
Bytecode parity: align borrow optimization with CFG traversal#7773youknowone merged 6 commits intoRustPython:mainfrom
Conversation
📝 WalkthroughWalkthroughThree independent changes: spell-check word additions, compiler symbol-table free-variable analysis refinement for cell scopes, and temporary file handling in bytecode comparison script. ChangesSpell-Check Configuration
Symbol-Table Free-Variable Analysis
Bytecode Comparison Script
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes 🎯 3 (Moderate) | ⏱️ ~25 minutes 🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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 |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_coroutines.py (TODO: 18) dependencies: dependent tests: (7 tests) [x] test: cpython/Lib/test/test_compile.py (TODO: 16) dependencies: dependent tests: (no tests depend on compile) Legend:
|
- compile.rs: unwind_fblock_stack returns whether a finally ran so return-statement emission can adjust location handling; restructure try/except/finally cleanup to preserve or drop boundary NOPs based on whether the body falls through; rework f-string lowering with count/join helpers; remove the per-collection-type heuristic for AST-level folding and defer to flowgraph passes; add several folding helpers and a ComprehensionLoopControl enum. - ir.rs: re-run unary/binop folding around tuple folding, add reorder_conditional_scope_exit_and_jump_back_blocks and several block classification helpers, add MAX_STR_SIZE, change is_exit_without_lineno to take the block list. - symboltable.rs: in analyze_cells, remove names owned as cells in function-like scopes from the parent's free set; mark lambda scope type explicitly.
e6c29b9 to
a24ceb9
Compare
a24ceb9 to
e04ca46
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/codegen/src/symboltable.rs (2)
594-643: 💤 Low valueOptional: deduplicate the function-like scope predicate.
remove_owned_cells_from_free(594–601) andpromote_inlined_cells_to_cell(628–635) test the exact same set ofCompilerScopevariants. Extracting a small helper such asis_function_like_scope(typ)(or a single local bound once) would prevent the two lists from drifting if future scope variants are added (e.g. a new type-param-like scope that should — or shouldn't — be considered function-like for both passes).♻️ Sketch
fn is_function_like(typ: CompilerScope) -> bool { matches!( typ, CompilerScope::Function | CompilerScope::AsyncFunction | CompilerScope::Lambda | CompilerScope::Comprehension | CompilerScope::Annotation ) }Then reuse at both call sites.
🤖 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 594 - 643, The two boolean predicates remove_owned_cells_from_free and promote_inlined_cells_to_cell duplicate the same matches(...) over symbol_table.typ; refactor by extracting a small helper (e.g. is_function_like or is_function_like_scope) that accepts a CompilerScope (or the symbol_table.typ) and returns whether it is one of Function | AsyncFunction | Lambda | Comprehension | Annotation, then replace both match expressions with calls to that helper (update the uses around symbol_table.typ so remove_owned_cells_from_free and promote_inlined_cells_to_cell are computed via is_function_like(symbol_table.typ) or by binding the helper result once).
2131-2153: 💤 Low valueLambda scope type set post-hoc — consider threading the scope type through the helper instead.
enter_scope_with_parametersalways creates the scope asFunction/AsyncFunctionbased onis_async, so the new line 2146 patches the typ back toLambdaonly on the with-parameters path; the without-parameters branch (line 2148) already passesLambdadirectly. Functionally this works because parameter registration doesn't observetypin a way that differs between Function and Lambda, and the new cell-pruning logic at lines 594–601 already treats Lambda as function-like.That said, the post-hoc mutation is easy to overlook for future readers. A cleaner long-term shape would be to pass the scope kind into
enter_scope_with_parameters(e.g. an enum or a dedicatedis_lambda: bool) so both branches construct the table with the finaltypfrom the start. Optional in this PR.🤖 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 2131 - 2153, The Lambda branch mutates the scope.kind after calling enter_scope_with_parameters because that helper currently infers Function/AsyncFunction from is_async; modify enter_scope_with_parameters to accept an explicit scope kind (e.g., a new enum parameter like scope_kind or a boolean is_lambda) and use that when constructing the new CompilerScope table so the created scope is Lambda from the start; update the Expr::Lambda call site to pass the Lambda kind (and preserve existing async handling for other callers), and adjust any internal logic in enter_scope_with_parameters that previously derived typ from is_async to instead use the provided scope kind.
🤖 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.
Nitpick comments:
In `@crates/codegen/src/symboltable.rs`:
- Around line 594-643: The two boolean predicates remove_owned_cells_from_free
and promote_inlined_cells_to_cell duplicate the same matches(...) over
symbol_table.typ; refactor by extracting a small helper (e.g. is_function_like
or is_function_like_scope) that accepts a CompilerScope (or the
symbol_table.typ) and returns whether it is one of Function | AsyncFunction |
Lambda | Comprehension | Annotation, then replace both match expressions with
calls to that helper (update the uses around symbol_table.typ so
remove_owned_cells_from_free and promote_inlined_cells_to_cell are computed via
is_function_like(symbol_table.typ) or by binding the helper result once).
- Around line 2131-2153: The Lambda branch mutates the scope.kind after calling
enter_scope_with_parameters because that helper currently infers
Function/AsyncFunction from is_async; modify enter_scope_with_parameters to
accept an explicit scope kind (e.g., a new enum parameter like scope_kind or a
boolean is_lambda) and use that when constructing the new CompilerScope table so
the created scope is Lambda from the start; update the Expr::Lambda call site to
pass the Lambda kind (and preserve existing async handling for other callers),
and adjust any internal logic in enter_scope_with_parameters that previously
derived typ from is_async to instead use the provided scope kind.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: df128704-a615-42bb-b02d-227922125963
⛔ Files ignored due to path filters (2)
Lib/test/test_coroutines.pyis excluded by!Lib/**Lib/test/test_peepholer.pyis excluded by!Lib/**
📒 Files selected for processing (5)
.cspell.jsoncrates/codegen/src/compile.rscrates/codegen/src/ir.rscrates/codegen/src/symboltable.rsscripts/compare_bytecode.py
Summary
Align LOAD_FAST_BORROW optimization with CPython-style CFG traversal instead of post-processing bytecode after borrow optimization.
Details
optimize_load_fast_borrow, so those blocks are excluded during traversal rather than rewritten afterward.POP_EXCEPTand then return/continue normally as resuming handlers, avoiding over-deoptimization after conditional reraises.GET_ANEXT/SENDiterator paths are not mistaken for relevant async-finally sends.imaplib.Idler.__exit__-style debug tails and thetest_compile.pyasync comprehension capture case.Validation
cargo fmtcargo test -p rustpython-codegen test_match_async_comprehension_iter_keeps_capture_borrow -- --nocapturecargo test -p rustpython-codegen test_imap_idle_status_debug_tail_keeps_borrow -- --nocapturecargo test -p rustpython-codegen deopts -- --nocapturecargo build --releasepython scripts/compare_bytecode.py --filter 'test/test_compile.py' --detail --max-diffs 300 -j 1 -o /tmp/compare_test_compile.after_rebase.reportpython scripts/compare_bytecode.py --filter 'imaplib.py' --detail --max-diffs 200 -j 1 -o /tmp/compare_imaplib.after_rebase.reportSummary by CodeRabbit