diff --git a/newsfragments/2676.added.md b/newsfragments/2676.added.md new file mode 100644 index 00000000000..2dd96585e3a --- /dev/null +++ b/newsfragments/2676.added.md @@ -0,0 +1 @@ +Implemented `ExactSizeIterator` for `PyListIterator`, `PyDictIterator`, `PySetIterator` and `PyFrozenSetIterator` diff --git a/src/types/dict.rs b/src/types/dict.rs index 49eb5f41d15..853a45af5c3 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -310,11 +310,17 @@ impl<'py> Iterator for PyDictIterator<'py> { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.len as usize; + let len = self.len(); (len, Some(len)) } } +impl<'py> ExactSizeIterator for PyDictIterator<'py> { + fn len(&self) -> usize { + self.len as usize + } +} + impl<'a> std::iter::IntoIterator for &'a PyDict { type Item = (&'a PyAny, &'a PyAny); type IntoIter = PyDictIterator<'a>; diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index 704c2591af4..02ac0f106fa 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -119,7 +119,7 @@ mod impl_ { /// PyO3 implementation of an iterator for a Python `frozenset` object. pub struct PyFrozenSetIterator<'py> { - set: &'py PyAny, + set: &'py PyFrozenSet, pos: ffi::Py_ssize_t, } @@ -143,11 +143,14 @@ mod impl_ { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.set.len().unwrap_or_default(); - ( - len.saturating_sub(self.pos as usize), - Some(len.saturating_sub(self.pos as usize)), - ) + let len = self.len(); + (len, Some(len)) + } + } + + impl<'py> ExactSizeIterator for PyFrozenSetIterator<'py> { + fn len(&self) -> usize { + self.set.len().saturating_sub(self.pos as usize) } } } diff --git a/src/types/list.rs b/src/types/list.rs index 40e717ef9a7..e12d34bbed2 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -322,12 +322,14 @@ impl<'a> Iterator for PyListIterator<'a> { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.list.len(); + let len = self.len(); + (len, Some(len)) + } +} - ( - len.saturating_sub(self.index), - Some(len.saturating_sub(self.index)), - ) +impl<'a> ExactSizeIterator for PyListIterator<'a> { + fn len(&self) -> usize { + self.list.len().saturating_sub(self.index) } } diff --git a/src/types/set.rs b/src/types/set.rs index 0488ee3445a..fbe5df64aaf 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -169,7 +169,7 @@ mod impl_ { /// PyO3 implementation of an iterator for a Python `set` object. pub struct PySetIterator<'py> { - set: &'py super::PyAny, + set: &'py super::PySet, pos: ffi::Py_ssize_t, used: ffi::Py_ssize_t, } @@ -219,11 +219,14 @@ mod impl_ { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.set.len().unwrap_or_default(); - ( - len.saturating_sub(self.pos as usize), - Some(len.saturating_sub(self.pos as usize)), - ) + let len = self.len(); + (len, Some(len)) + } + } + + impl<'py> ExactSizeIterator for PySetIterator<'py> { + fn len(&self) -> usize { + self.set.len().saturating_sub(self.pos as usize) } } } diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 84165e1fce3..e86689b773d 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -242,16 +242,14 @@ impl<'a> Iterator for PyTupleIterator<'a> { #[inline] fn size_hint(&self) -> (usize, Option) { - ( - self.length.saturating_sub(self.index as usize), - Some(self.length.saturating_sub(self.index as usize)), - ) + let len = self.len(); + (len, Some(len)) } } impl<'a> ExactSizeIterator for PyTupleIterator<'a> { fn len(&self) -> usize { - self.length - self.index + self.length.saturating_sub(self.index) } }