Returning &mut parameter in Iterator tuple

Hi! I would like to implement a function that takes a &mut reference, changes it and then returns an iterator that uses the same reference. Something like this:

 struct A {
    items: Vec<u32>
}
impl A {
    pub fn iter<'a>(&mut self, i: &'a mut u32) -> impl Iterator<Item = (&u32, &'a mut u32)> + '_ /* ??? */ {
        *i = 100;
        self.items
            .iter()
            .map(|v| {
                // ???
                (v, i)
            })
    }
}

fn main() {
    let a = A { items: vec!(1, 2, 3) };
    let mut i = 0;
    
    for (x, i) in a.iter(&mut i) {
        *i = *i + x;
    }
    
    println!("{}", i);
}

However, I'm having trouble with the parts marked with ???. What should the return type and can the mutable reference even be mapped like that?

It can't, since different items yielded by the iterator would have the same mutable reference inside them, which is forbidden.

Ah, makes sense after wrapping my head around it. Thanks

If only one iterator item exists at a time, it should be possible. I tried to make this work by using a RefCell to push the &mut aliasing check to runtime, but there’s a lifetime error I can’t get past.

It looks like the compiler is either refusing to move the RefCell into the closure or inferring that the closure might outlive ’a. It can’t, though, because it’s embedded in an object that is also bound by ’a and there’s no way to take the closure out of the Map object.

Can you spot either where my logic is wrong, or how to convince the compiler this is ok?
(Playground)

    pub fn iter<'a>(&'a mut self, i: &'a mut u32) -> impl 'a + Iterator<Item = (&'a u32, RefMut<'a, u32>)> {
        *i = 100;
        let cell = RefCell::new(i);
        self.items
            .iter()
            .map( move |v| (v, RefMut::map(cell.borrow_mut(), |i| *i) ) )
    }
   Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:12:49
   |
12 |             .map( move |v| (v, RefMut::map(cell.borrow_mut(), |i| *i) ) )
   |                                                 ^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 12:19...
  --> src/main.rs:12:19
   |
12 |             .map( move |v| (v, RefMut::map(cell.borrow_mut(), |i| *i) ) )
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `cell`
  --> src/main.rs:12:44
   |
12 |             .map( move |v| (v, RefMut::map(cell.borrow_mut(), |i| *i) ) )
   |                                            ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the method body at 7:17...
  --> src/main.rs:7:17
   |
7  |     pub fn iter<'a>(&'a mut self, i: &'a mut u32) -> impl 'a + Iterator<Item = (&'a u32, RefMut<'a, u32>)> {
   |                 ^^
note: ...so that the types are compatible
  --> src/main.rs:7:54
   |
7  |     pub fn iter<'a>(&'a mut self, i: &'a mut u32) -> impl 'a + Iterator<Item = (&'a u32, RefMut<'a, u32>)> {
   |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `(&u32, std::cell::RefMut<'_, _>)`
              found `(&'a u32, std::cell::RefMut<'a, _>)`

If I understand correclty, it is possible indeed - check the streaming_iterator crate.

As for your main question:

But there's no way to prove this, either. Compiler is free to assume that you can somehow get an exclusive reference to this closure and then mem::swap it with another one, it doesn't treat Map object as something special.

True, but we have a named lifetime ’a that’s limiting everything here; the iterator itself already can’t outlive ’a because it’s yielding ’a references. The closure type also can’t outlive ’a for the same reason, even if it’s separated from the iterator. Where’s the (potentially) longer-than-’a lifetime bound coming from?

Are the anonymous types created by closure syntax required to be ’static?

Edit: I figured it out: there’s no guarantee that Map will keep the closure alive after using its return value, so it can’t return a reference to a captured value.

In this particular case, using Cell would be much better than RefCell. There's even a method to turn a mutable reference into an immutable reference to a Cell.

1 Like

That ended up working fairly easily (Playground). I also got something working that produced Rc<RefCell<&’a mut u32>>, but was having trouble coming up with an RAII wrapper implementation that both owned the Rc and implemented DerefMut<Target=u32>+’a

The issue you are running into with RefCell is that RefCell is invariant, which can cause trouble with the impl Trait syntax when all the lifetimes cannot be reduced to a single lifetime.

1 Like

I managed to get this to work, but it took a little bit of unsafe and more code than is really justified for such a toy problem: (Playground)

use std::{
    cell::{RefCell,RefMut},
    ops::{Deref,DerefMut},
    rc::Rc,
    pin::Pin,
};

#[derive(Clone,Debug)]
struct RcCell<T>(Pin<Rc<RefCell<T>>>);
impl<T> RcCell<T> {
    fn new(init:T)->Self { RcCell(Rc::pin(RefCell::new(init))) }
    fn borrow_mut<'a>(&self)->RcCellRefMut<'a, T, T> where T:'a {
            let cloned:RcCell<T> = RcCell(Pin::clone(&self.0));
            unsafe { // Transmute is ok b/c the Pin<Rc<...>> guarantees the
                     // referent remains alive and unmoved.
                RcCellRefMut(cloned,
                             std::mem::transmute(self.0.borrow_mut()) )
            }
    }
}

struct RcCellRefMut<'a, Cell, Inner>(RcCell<Cell>, RefMut<'a, Inner>);

impl<'a,Cell,Inner> Deref for RcCellRefMut<'a,Cell,Inner> {
    type Target = Inner;
    fn deref(& self)->& Inner {
        self.1.deref()
    }
}

impl<'a,Cell,Inner> DerefMut for RcCellRefMut<'a,Cell,Inner> {
    fn deref_mut(&mut self)->&mut Inner {
        self.1.deref_mut()
    }
}

impl<'a,Cell,Inner> RcCellRefMut<'a,Cell,Inner> {
    pub fn map<U, F>(orig: RcCellRefMut<'a,Cell,Inner>, f: F) 
        -> RcCellRefMut<'a, Cell,U> where F: FnOnce(&mut Inner) -> &mut U
        {
            RcCellRefMut(orig.0, RefMut::map(orig.1, f))
        }
}

// ---------------

struct A {
    items: Vec<u32>
}

impl A {
    pub fn iter<'a>(&'a mut self, i: &'a mut u32)
        -> impl 'a + Iterator<Item = (&'a u32, impl 'a+DerefMut<Target=u32>)>
    {
        *i = 100;
        let cell = RcCell::new(i);
        self.items
            .iter()
            .map( move |v| (v, RcCellRefMut::map(cell.borrow_mut(),
                                                 |x: &mut &'a mut u32| *x )))
    }
}

fn main() {
    let mut a = A { items: vec!(1, 2, 3) };
    let mut i = 0;
    
    for (x, mut i) in a.iter(&mut i) {
        *i = *i + *x;
    }
    
    println!("{}", i);
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.