What guarantees does core::iter::Repeat give around observing calls to clone? · Issue #81292 · rust-lang/rust (original) (raw)
Currently, core::iter::Repeat::nth
calls core::iter::Repeat::next
n
times.
This allows a struct with interior mutability or other global state and a custom clone implementation to observe the number of times it has been cloned.
use std::sync::atomic::{AtomicUsize, Ordering};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
struct X;
impl Clone for X { fn clone(&self) -> Self { COUNTER.fetch_add(1, Ordering::SeqCst); Self } }
fn main() { let mut iter = core::iter::repeat(X); for _ in 0..10_000 { let _ = iter.next(); } println!("counter: {}", COUNTER.load(Ordering::SeqCst)); let _ = iter.nth(555); println!("counter: {}", COUNTER.load(Ordering::SeqCst)); }
Currently, this program outputs:
counter: 10000
counter: 10556
Would it be possible to override the implementations of some Iterator
methods that have default implementations without breaking any documented contract?
impl<A: Clone> Iterator for Repeat { type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
Some(self.element.clone())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::MAX, None)
}
#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
// Advancing an infinite iterator of a single element is a no-op.
let _ = n;
}
#[inline]
fn nth(&mut self, n: usize) -> Option<T> {
let _ = n;
Some(self.element.clone())
}
fn last(self) -> Option<T> {
loop {}
}
fn count(self) -> usize {
loop {}
}
}
impl<A: Clone> DoubleEndedIterator for Repeat { #[inline] fn next_back(&mut self) -> Option { Some(self.element.clone()) }
#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
// Advancing an infinite iterator of a single element is a no-op.
let _ = n;
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<T> {
let _ = n;
Some(self.element.clone())
}
}