diff --git a/vm/src/frame.rs b/vm/src/frame.rs index d62e538051..80f848fc94 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -925,7 +925,7 @@ impl ExecutingFrame<'_> { _ => None, }; - let exit = self.pop_value(); + let exit = self.top_value(); let args = if let Some(exc) = exc { vm.split_exception(exc) @@ -933,7 +933,7 @@ impl ExecutingFrame<'_> { (vm.ctx.none(), vm.ctx.none(), vm.ctx.none()) }; let exit_res = exit.call(args, vm)?; - self.push_value(exit_res); + self.replace_top(exit_res); Ok(None) } @@ -994,7 +994,7 @@ impl ExecutingFrame<'_> { } bytecode::Instruction::GetANext => { let aiter = self.top_value(); - let awaitable = vm.call_special_method(&aiter, identifier!(vm, __anext__), ())?; + let awaitable = vm.call_special_method(aiter, identifier!(vm, __anext__), ())?; let awaitable = if awaitable.payload_is::() { awaitable } else { @@ -1911,8 +1911,18 @@ impl ExecutingFrame<'_> { }); } + #[track_caller] fn pop_block(&mut self) -> Block { let block = self.state.blocks.pop().expect("No more blocks to pop!"); + #[cfg(debug_assertions)] + if self.state.stack.len() < block.level { + dbg!(&self); + panic!( + "stack size reversion: current size({}) < truncates target({}).", + self.state.stack.len(), + block.level + ); + } self.state.stack.truncate(block.level); block } @@ -1945,7 +1955,14 @@ impl ExecutingFrame<'_> { } #[inline] - #[track_caller] // not a real track_caller but pop_value is not very useful + fn replace_top(&mut self, mut top: PyObjectRef) -> PyObjectRef { + let last = self.state.stack.last_mut().unwrap(); + std::mem::swap(&mut top, last); + top + } + + #[inline] + #[track_caller] // not a real track_caller but top_value is not very useful fn top_value(&self) -> &PyObject { match &*self.state.stack { [.., last] => last,