diff --git a/vm/src/function/argument.rs b/vm/src/function/argument.rs index d9fc1ac15..e6b6f24d8 100644 --- a/vm/src/function/argument.rs +++ b/vm/src/function/argument.rs @@ -55,7 +55,7 @@ impl ArgIterable { Some(f) => f(self.iterable.clone(), vm)?, None => PySequenceIterator::new(self.iterable.clone()).into_object(vm), }); - iter.iter(vm) + iter.into_iter(vm) } } @@ -72,7 +72,7 @@ where return Err(vm.new_type_error(format!("'{}' object is not iterable", cls.name()))); } } - Ok(ArgIterable { + Ok(Self { iterable: obj, iterfn, _item: PhantomData, diff --git a/vm/src/protocol/iter.rs b/vm/src/protocol/iter.rs index e08755652..16a0e3cd7 100644 --- a/vm/src/protocol/iter.rs +++ b/vm/src/protocol/iter.rs @@ -10,9 +10,9 @@ use std::ops::Deref; // https://docs.python.org/3/c-api/iter.html #[derive(Debug, Clone)] #[repr(transparent)] -pub struct PyIter(T) +pub struct PyIter(O) where - T: Borrow; + O: Borrow; impl PyIter { pub fn into_object(self) -> PyObjectRef { @@ -25,11 +25,11 @@ impl PyIter { } } -impl PyIter +impl PyIter where - T: Borrow, + O: Borrow, { - pub fn new(obj: T) -> Self { + pub fn new(obj: O) -> Self { Self(obj) } pub fn as_object(&self) -> &PyObjectRef { @@ -51,29 +51,35 @@ where iternext(self.0.borrow(), vm) } - pub fn iter<'a, U>(&self, vm: &'a VirtualMachine) -> PyResult> { - let obj = self.as_object(); - let length_hint = vm.length_hint(obj.clone())?; - Ok(PyIterIter::new( - vm, - PyIter::::new(obj.clone()), - length_hint, - )) + pub fn iter<'a, 'b, U>( + &'b self, + vm: &'a VirtualMachine, + ) -> PyResult> { + let length_hint = vm.length_hint(self.as_object().clone())?; + Ok(PyIterIter::new(vm, self.0.borrow(), length_hint)) } } -impl Borrow for PyIter +impl PyIter { + /// Returns an iterator over this sequence of objects. + pub fn into_iter(self, vm: &VirtualMachine) -> PyResult> { + let length_hint = vm.length_hint(self.as_object().clone())?; + Ok(PyIterIter::new(vm, self.0, length_hint)) + } +} + +impl Borrow for PyIter where - T: Borrow, + O: Borrow, { fn borrow(&self) -> &PyObjectRef { self.0.borrow() } } -impl Deref for PyIter +impl Deref for PyIter where - T: Borrow, + O: Borrow, { type Target = PyObjectRef; fn deref(&self) -> &Self::Target { @@ -188,15 +194,21 @@ impl IntoPyResult for PyResult { } // Typical rust `Iter` object for `PyIter` -pub struct PyIterIter<'a, T> { +pub struct PyIterIter<'a, T, O = PyObjectRef> +where + O: Borrow, +{ vm: &'a VirtualMachine, - obj: PyIter, + obj: O, // creating PyIter is zero-cost length_hint: Option, _phantom: std::marker::PhantomData, } -impl<'a, T> PyIterIter<'a, T> { - pub fn new(vm: &'a VirtualMachine, obj: PyIter, length_hint: Option) -> Self { +impl<'a, T, O> PyIterIter<'a, T, O> +where + O: Borrow, +{ + pub fn new(vm: &'a VirtualMachine, obj: O, length_hint: Option) -> Self { Self { vm, obj, @@ -206,14 +218,15 @@ impl<'a, T> PyIterIter<'a, T> { } } -impl<'a, T> Iterator for PyIterIter<'a, T> +impl<'a, T, O> Iterator for PyIterIter<'a, T, O> where T: TryFromObject, + O: Borrow, { type Item = PyResult; fn next(&mut self) -> Option { - self.obj + PyIter::new(self.obj.borrow()) .next(self.vm) .map(|iret| match iret { PyIterReturn::Return(obj) => Some(obj),