Iterator cannot move out of borrowed content

hello everyone I have this code:

impl FetchJob
{
    pub fn fetch_chunk<I>(chunk: usize, iter: Arc<Mutex<I>>) -> impl Future<Item = bool, Error = ()>
    where
        I: Iterator<Item = hyper::Uri>
    {
        //let client = build_https_client().unwrap(); //TODO make this at initialization to not remake the client at every interval.
        let client = Client::new();
        let mut requests: Vec<_> = Vec::new();
        for (uri, count) in &*iter.lock().expect("error") {
            requests.push(client
                .clone()
                .get(uri)
                .map(|res| {
                    println!("Response: {}", res.status());
                    println!("Headers: {:#?}", res.headers());
                })
                .map_err(|e| println!("{:#?}", e)));
        }
        future::join_all(requests)
            .map(move |res: Vec<()>| res.len() == chunk)
            .map_err(|_| ())
    }
}

struct FetchStream<I> {
    uri_iter: Arc<Mutex<I>>,
    interval: Interval,
    time_pass: TimePass,
    fetch_job: FetchJob,
    fetch_future: Option<Box<dyn Future<Item = bool, Error = ()> + Send>>,
}

impl<I> FetchStream<I> {
    pub fn new(chunk: usize, interval: std::time::Duration, iter: I ) -> Self {
        Self {
            uri_iter: Arc::new(Mutex::new(iter)),
            interval: Interval::new_interval(interval),
            time_pass: TimePass::Ready,
            fetch_job: FetchJob {
                chunk
            },
            fetch_future: None
        }
    }
}

impl<I> Future for FetchStream<I>
where
    I: Iterator<Item = hyper::Uri> + 'static,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, ()> {
        loop {
            match self.time_pass {
                TimePass::Ready => {
                    if let Some(_) = self.fetch_future {
                        let res: bool = try_ready!(self.fetch_future.poll().map_err(|_| ())).unwrap();
                        if !res {
                            return Ok(Async::Ready(()))
                        }
                    } else {
                        let iter = self.uri_iter.clone();
                        self.fetch_future: Option<Box<dyn Future<Item = bool, Error = ()> + Send>> =
                            Some(Box::new(FetchJob::fetch_chunk(23, iter)));

but it gives me:

error[E0277]: `&I` is not an iterator
  --> src/fetch/fetch_stream.rs:86:29
   |
86 |         for (uri, count) in &*iter.lock().expect("error") {
   |                             -^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                             |
   |                             `&I` is not an iterator
   |                             help: consider removing 1 leading `&`-references
   |
   = help: the trait `std::iter::Iterator` is not implemented for `&I`
   = note: required by `std::iter::IntoIterator::into_iter`

but even if I take off the & I get:

error[E0507]: cannot move out of borrowed content
  --> src/fetch/fetch_stream.rs:85:20
   |
85 |         for uri in *iter.lock().expect("error") {
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

I have a Arc<mutex<>> around it so I don't see why it is complaining about it.

For loop needs an owned iterator and locking a mutex will give you only a temporary &mut borrow. Fortunately, there's a by_ref wrapper that allows you to treat a reference to iterator also as iterator:

for uri in iter.lock().expect("error").by_ref() { … }

Please note that after such a loop the iterator would be drained and any second attempt to iterate will return no items.

Sidenote: If by_ref wrapper did not exist, you could also iterate “manually”:

let mut locked_iter = iter.lock().expect("error");
while let Some(item) = locked_iter.next() { … }

The thing is that it will be called into this function multiple times with the same iterator

Is there a way to go around this?

Oh, let me try the manual way

You can require Clone on your iterator, and clone the actual iterator (without the Mutex).

Perhaps you don't want an Iterator bound on I but IntoIterator?

Note that the while let loop will have the same draining behaviour as by_ref.

I saw the IntoIterator implementation for Vec but it just calls some self.iter() method which I did not find a def for. I do not know how to implement IntoIter

Do you have a sample implementation for IntoIterator? This is what I have currently:

impl Iterator for TestSource {
    type Item = Uri;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count == 3 {
            None
        } else {
            Some(self.url.clone().parse::<hyper::Uri>().unwrap())
        }
    }
}

how would I convert this into a IntoIterator that will work in a for loop with as a reference?

well the while will also drain it unless you call break.

You may want to split TestSource to TestSource and TestSourceIter:

struct TestSourceIter {
    // all the fields from your TestSource
}

impl Iterator for TestSourceIter {
    type Item = Uri;

    fn next(&mut self) -> Option<Self::Item> { /* same as before */ }
}

struct TestSource {
    // fields that are needed to create TestSourceIter (so probably url, but not count)
}

impl IntoIterator for TestSource {
    type Item = Uri;
    type IntoIter: TestSourceIter;
    fn into_iter(self) -> TestSourceIter { … }
}

This solution will also require cloning just before iterator. You can also impl IntoIterator for &TestSource instead, but I think it'll be harder to write a bound for that:

impl<'a> IntoIterator for &'a TestSource {
    type Item = Uri;
    type IntoIter: TestSourceIter;
    fn into_iter(self) -> TestSourceIter { … }
}

ok thanks I will try that out.