Split stack_effect into pushed & popped#6893
Conversation
📝 WalkthroughWalkthroughRefactors stack-effect handling by introducing a new Changes
Sequence Diagram(s)sequenceDiagram
participant Codegen as Codegen (crates/codegen)
participant Stdlib as Stdlib (_opcode)
participant Compiler as Compiler-core (AnyInstruction / Instruction)
participant OpArg as OpArg (converter)
Note over Codegen,Stdlib: Obtain numeric oparg and request stack effect
Codegen->>OpArg: convert/forward oparg -> u32 (use `.into()` where needed)
Stdlib->>OpArg: use oparg as u32 / forward as-is
Codegen->>Compiler: call stack_effect_info(u32) or stack_effect(u32)
Stdlib->>Compiler: call stack_effect(u32)
Compiler-->>Codegen: return StackEffect (pushed,popped) / .effect()
Compiler-->>Stdlib: return StackEffect (pushed,popped) / .effect()
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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.
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 (1)
crates/stdlib/src/_opcode.rs (1)
169-201: Add validation to reject negativeopargvalues.CPython's
dis.stack_effecttreatsopargas an unsigned bytecode argument and raisesValueError("invalid opcode or oparg")ifopargis negative. Your change fromu32toi32allows negatives to pass through unchecked, creating a compatibility divergence. Add a guard:if oparg < 0 { return Err(vm.new_value_error("oparg must be non-negative")); }
🤖 Fix all issues with AI agents
In `@crates/codegen/src/ir.rs`:
- Line 734: Replace the unchecked cast u32::from(info.arg) as i32 with a checked
conversion using i32::try_from(u32::from(info.arg)) and handle the Err case
instead of allowing silent wraparound; specifically, call
instr.stack_effect(i32::try_from(u32::from(info.arg)).expect("OpArg out of i32
range")) or propagate an error if appropriate for your context, and make the
same replacement for the other occurrence noted (the second use of
instr.stack_effect with info.arg).
In `@crates/compiler-core/src/bytecode/instruction.rs`:
- Around line 900-906: The match arm for the opcode BinaryOpInplaceAddUnicode
currently returns 0 pushes which contradicts the IR treatment (pop 2 / push 1)
and causes stack_effect = -2; update the implementation that computes pushes
(e.g., num_pushed or the match in instruction.rs where BinaryOpInplaceAddUnicode
is handled) to return 1 like the other binary ops
(BinaryOpAddFloat/Int/Unicode/Extend/Multiply) so the stack depth calculation
matches the IR semantics.
Sorry, something went wrong.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@crates/compiler-core/src/bytecode/instruction.rs`:
- Around line 1396-1435: The From<StackEffect> for i32 impl uses unsafe
unwrap_unchecked on conversions of StackEffect.pushed() and .popped(), which can
UB if values exceed i32::MAX; replace the unsafe block by performing safe
conversions (use i32::try_from(...) and propagate or panic with expect including
the offending value), e.g. convert pushed and popped to i32 via try_from and
subtract normally, and update StackEffect::effect() to rely on this safe
conversion; also fix the "SAFTEY" typo to "SAFETY" in the comment to avoid
confusion.
Sorry, something went wrong.
743d6b8
into
RustPython:main
Jan 31, 2026
Auto generated both
num_poppedandnum_pushed, and then compared the result with the currentstack_effectimpl. This will make it easier to auto-generate this in the future, and gets us 1 step closer to #6746 as imo it's better to construct the instruction once instead of validate that the oparg is valid at every operation. Also, it's easier to see if we differences in our opcode impls from CPython (if the stack_effect does not match)Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.