diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 3ccef016f..41b2aceab 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -1043,7 +1043,7 @@ impl Frame { fn execute_unpack_ex(&self, vm: &VirtualMachine, before: usize, after: usize) -> FrameResult { let value = self.pop_value(); - let elements = vm.extract_elements(&value)?; + let elements = vm.extract_elements::(&value)?; let min_expected = before + after; if elements.len() < min_expected { Err(vm.new_value_error(format!( diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 61267968d..bbf4c3612 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -7,7 +7,7 @@ use std::cell::Cell; use super::objtuple::PyTuple; use super::objtype::{self, PyClassRef}; use crate::pyobject::{ - PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, + PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -60,14 +60,10 @@ pub fn get_next_object( } /* Retrieve all elements from an iterator */ -pub fn get_all(vm: &VirtualMachine, iter_obj: &PyObjectRef) -> PyResult> { +pub fn get_all(vm: &VirtualMachine, iter_obj: &PyObjectRef) -> PyResult> { let mut elements = vec![]; - loop { - let element = get_next_object(vm, iter_obj)?; - match element { - Some(v) => elements.push(v), - None => break, - } + while let Some(element) = get_next_object(vm, iter_obj)? { + elements.push(T::try_from_object(vm, element)?); } Ok(elements) } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 6469b545a..60de10c85 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -941,6 +941,7 @@ where } impl TryFromObject for PyObjectRef { + #[inline] fn try_from_object(_vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { Ok(obj) } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 06cceb143..cec48f449 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -808,17 +808,22 @@ impl VirtualMachine { Ok(()) } - pub fn extract_elements(&self, value: &PyObjectRef) -> PyResult> { + pub fn extract_elements(&self, value: &PyObjectRef) -> PyResult> { // Extract elements from item, if possible: - let elements = if objtype::isinstance(value, &self.ctx.tuple_type()) { - objsequence::get_elements_tuple(value).to_vec() + if objtype::isinstance(value, &self.ctx.tuple_type()) { + objsequence::get_elements_tuple(value) + .iter() + .map(|obj| T::try_from_object(self, obj.clone())) + .collect() } else if objtype::isinstance(value, &self.ctx.list_type()) { - objsequence::get_elements_list(value).to_vec() + objsequence::get_elements_list(value) + .iter() + .map(|obj| T::try_from_object(self, obj.clone())) + .collect() } else { let iter = objiter::get_iter(self, value)?; - objiter::get_all(self, &iter)? - }; - Ok(elements) + objiter::get_all(self, &iter) + } } // get_attribute should be used for full attribute access (usually from user code).