Skip to content

Commit 239ff88

Browse files
committed
Fix "tried to pop from empty stack" with BlockExpr and const
Constant expressions without side effects are optimized away unless in an interactive mode[1]. This causes panic when last statement in a block is a constant and Mode::BlockExpr is used as this constant value must be returned to caller. Example panic: ---- vm::python_run::tests::test_block_expr_return_const stdout ---- [crates/vm/src/frame.rs:9653:9] self = ExecutingFrame { code: code: <code object <module> at ??? file "<embedded>", line 1>, stack_len: 0, } thread 'vm::python_run::tests::test_block_expr_return_const' (2640752) panicked at crates/vm/src/frame.rs:9410:18: tried to pop from empty stack stack backtrace: 0: __rustc::rust_begin_unwind at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5 1: core::panicking::panic_fmt at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:80:14 2: rustpython_vm::frame::ExecutingFrame::fatal at ./src/frame.rs:9654:9 3: rustpython_vm::frame::ExecutingFrame::pop_stackref_opt at ./src/frame.rs:9410:18 4: rustpython_vm::frame::ExecutingFrame::pop_stackref at ./src/frame.rs:9420:18 5: rustpython_vm::frame::ExecutingFrame::pop_value at ./src/frame.rs:9435:14 6: rustpython_vm::frame::ExecutingFrame::execute_instruction at ./src/frame.rs:3391:34 7: rustpython_vm::frame::ExecutingFrame::run at ./src/frame.rs:1623:31 8: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::run::{{closure}} at ./src/frame.rs:1098:44 9: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::with_exec at ./src/frame.rs:1093:9 10: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::run at ./src/frame.rs:1098:14 11: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}} at ./src/vm/mod.rs:1201:44 12: rustpython_vm::vm::VirtualMachine::with_frame_impl::{{closure}}::{{closure}} at ./src/vm/mod.rs:1610:60 13: rustpython_vm::vm::VirtualMachine::dispatch_traced_frame at ./src/vm/mod.rs:1689:22 14: rustpython_vm::vm::VirtualMachine::with_frame_impl::{{closure}} at ./src/vm/mod.rs:1610:22 15: rustpython_vm::vm::VirtualMachine::with_recursion at ./src/vm/mod.rs:1547:9 16: rustpython_vm::vm::VirtualMachine::with_frame_impl at ./src/vm/mod.rs:1572:14 17: rustpython_vm::vm::VirtualMachine::with_frame at ./src/vm/mod.rs:1555:14 18: rustpython_vm::vm::VirtualMachine::run_frame at ./src/vm/mod.rs:1201:20 19: rustpython_vm::vm::VirtualMachine::run_code_obj at ./src/vm/mod.rs:1120:14 20: rustpython_vm::vm::python_run::<impl rustpython_vm::vm::VirtualMachine>::run_block_expr at ./src/vm/python_run.rs:51:14 21: rustpython_vm::vm::python_run::tests::test_block_expr_return_const::{{closure}} at ./src/vm/python_run.rs:190:47 22: rustpython_vm::vm::interpreter::Interpreter::enter::{{closure}} at ./src/vm/interpreter.rs:366:39 23: rustpython_vm::vm::thread::set_current_vm::{{closure}} at ./src/vm/thread.rs:107:9 24: std::thread::local::LocalKey<T>::try_with at /home/im/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:513:12 25: std::thread::local::LocalKey<T>::with at /home/im/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:477:20 26: rustpython_vm::vm::thread::set_current_vm at ./src/vm/thread.rs:102:14 27: rustpython_vm::vm::thread::enter_vm at ./src/vm/thread.rs:132:5 28: rustpython_vm::vm::interpreter::Interpreter::enter at ./src/vm/interpreter.rs:366:9 29: rustpython_vm::vm::python_run::tests::test_block_expr_return_const at ./src/vm/python_run.rs:188:23 30: rustpython_vm::vm::python_run::tests::test_block_expr_return_const::{{closure}} at ./src/vm/python_run.rs:187:38 31: core::ops::function::FnOnce::call_once at /home/im/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5 32: <fn() -> core::result::Result<(), alloc::string::String> as core::ops::function::FnOnce<()>>::call_once at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:250:5 [1] https://github.com/RustPython/RustPython/blob/883ce9d273db98b435eb3f51128925a1255ba88d/crates/codegen/src/compile.rs#L2990-L2997
1 parent 899fac4 commit 239ff88

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

crates/codegen/src/compile.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,8 +2499,12 @@ impl Compiler {
24992499

25002500
if let Some(last_statement) = body.last() {
25012501
match last_statement {
2502-
ast::Stmt::Expr(_) => {
2503-
self.current_block().instructions.pop(); // pop Instruction::PopTop
2502+
ast::Stmt::Expr(ast::StmtExpr { value, .. }) => {
2503+
if !self.interactive && Self::is_const_expression(value) {
2504+
self.compile_expression(value)?;
2505+
} else {
2506+
self.current_block().instructions.pop(); // pop Instruction::PopTop
2507+
}
25042508
}
25052509
ast::Stmt::FunctionDef(_) | ast::Stmt::ClassDef(_) => {
25062510
let pop_instructions = self.current_block().instructions.pop();

0 commit comments

Comments
 (0)