Help about multiple mutable borrows

Hi,

I'm new to Rust and I'm trying to write a miniflow data struct used in open vswitch. I'm stuck at this error due to multiple mutable borrows. Any suggestion or things to read are welcome. Thanks!

use std::usize;
struct flowmap {
    bits: [u64; FLOWMAP_UNITS],
}

pub const FLOWMAP_UNITS:usize = 2;
pub const MAP_T_BITS:usize = 64;
pub const FLOW_U64S:usize = 84;

impl flowmap {
    pub fn new() -> flowmap {
        flowmap { 
            bits: [0; FLOWMAP_UNITS],
        }
    }
}

struct miniflow {
    pub map: flowmap,   // a bitmap
    pub values: [u64; FLOW_U64S],
}

impl miniflow {
    pub fn new() -> miniflow {
        miniflow {
            map: flowmap::new(), 
            values: [0; FLOW_U64S],
        }   
    }   
}

/* Context for pushing data to a miniflow. */
struct mf_ctx<'a> {
    map: flowmap,
    data: &'a mut [u64], 
    //end: &'a mut [u64], // cause multiple mutable borrow: XD
}

impl<'a> mf_ctx<'a> {
    pub fn from_mf(map_: flowmap, data_: &'a mut [u64]) -> mf_ctx<'a> {
        mf_ctx {
            map: map_, 
            data: data_,
        }
    }   

    pub fn miniflow_push_uint64_(&'a mut self, ofs: usize, value: u64) {
        self.data[0] = value;
        self.data = &mut self.data[1..]; // move self.data to next u64  
    }   
}

fn main() {
    println!("Hello, world!");

    let mut mf: miniflow = miniflow::new(); 
    let mut mfx = &mut mf_ctx::from_mf(mf.map, &mut mf.values);
    
    let ofs = 0;
    mfx.miniflow_push_uint64_(ofs, 1234);
    mfx.miniflow_push_uint64_(ofs + 1, 1234);
}

I got error saying below, but I though I'm not creating another mutable borrower? I'm reusing the same one 'mfx', so I don't understand why this is an error...

error[E0499]: cannot borrow `*mfx` as mutable more than once at a time
   --> src/main.rs:104:5
    |
103 |     mfx.miniflow_push_uint64_(ofs, 1234);
    |     --- first mutable borrow occurs here
104 |     mfx.miniflow_push_uint64_(ofs + 1, 1234);
    |     ^^^
    |     |
    |     second mutable borrow occurs here
    |     first borrow later used here

Ah that's an unfortunate pitfall. You need to change &'a mut self to &mut self.

The reason it fails is that when you specify the lifetime 'a explicitly like that, you're saying that this function borrows the value for as long as that lifetime lives, but since this lifetime refers to the lifetime of the data inside itself, the borrow lasts as long as the value itself does.

One case where you'd want to use the 'a lifetime explicitly is if you want to have a function that replaces the value in the data field inside the struct. Of course, to put a new reference into that field, that reference needs to be using the 'a lifetime explicitly, as you would otherwise not be able to store it somewhere that exists after the function returns.

3 Likes

Hi Alice,

Thanks for your quick reply!
I try it but then hit another error which looks more confusing ...
so remove the 'a

    pub fn miniflow_push_uint64_(&mut self, ofs: usize, value: u64) {
        self.data[0] = value;
        self.data = &mut self.data[1..]; // move self.data to next u64  
    }   

and

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:57:26
   |
57 |         self.data = &mut self.data[1..]; // move self.data to next u64  
   |                          ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 55:5...
  --> src/main.rs:55:5
   |
55 | /     pub fn miniflow_push_uint64_(&mut self, ofs: usize, value: u64) {
56 | |         self.data[0] = value;
57 | |         self.data = &mut self.data[1..]; // move self.data to next u64  
58 | |     }   
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:57:26
   |
57 |         self.data = &mut self.data[1..]; // move self.data to next u64  
   |                          ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 47:6...
  --> src/main.rs:47:6
   |
47 | impl<'a> mf_ctx<'a> {
   |      ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:57:21
   |
57 |         self.data = &mut self.data[1..]; // move self.data to next u64  
   |                     ^^^^^^^^^^^^^^^^^^^

I think the easiest approach is to store an IterMut. You can call next on it which returns a mutable reference to the first element and increments the internal counter by one.

While this sounds like something that should be able to be done in an easier way, I can't find it.

It turns out you can do this.

1 Like

Thanks a lot for your help!

1 Like

What if one needs to return a immutable reference in addition to that? Like

struct Foo<'a>(&'a mut [u8]);

impl<'a> Foo<'a> {
    fn foo<'b>(&'b mut self) -> &[u8] {
        &self.0[0..1]
    }
}

Oh, it compiles, but I am not sure why it fails on https://github.com/dtolnay/request-for-implementation/issues/7#issuecomment-563387564, I guess maybe because the lifetime was inferred incorrectly?

The code you posted has the elided lifetime like this:

struct Foo<'a>(&'a mut [u8]);

impl<'a> Foo<'a> {
    fn foo<'b>(&'b mut self) -> &'b [u8] {
        &self.0[0..1]
    }
}

playground

but the code on your github corresponds to this:

struct Foo<'a>(&'a mut [u8]);

impl<'a> Foo<'a> {
    fn foo<'b>(&'b mut self) -> &'a [u8] {
        &self.0[0..1]
    }
}

playground

This fails with pretty much the same error. Normally when reborrowing a mutable reference, you will make the mutable reference unusable while the reborrow exists in order to avoid aliasing references, but by linking the reference to 'a you unlink it from self, so you are free to use self during the lifetime of the returned reference. For example, this compiles just fine: (but is horribly undefined behaviour)

struct Foo<'a>(&'a mut [u8]);
impl<'a> Foo<'a> {
    fn foo<'b>(&'b mut self) -> &'a [u8] {
        // transmute the lifetimes
        unsafe { std::mem::transmute(&self.0[0..1]) }
    }
}
fn main() {
    let mut arr = [0, 1, 2, 3];
    let mut foo = Foo(&mut arr);
    
    let ref1 = foo.foo();
    let ref2 = foo.foo();
    
    println!("{:?}", ref1);
    println!("{:?}", ref2);
}

playground

An example of code that uses this kind of lifetime dancing is IterMut, which approximately looks like this:

struct IterMut<'a, T: 'a> {
    // details ommitted, it actually uses raw pointers
    inner: &'a mut [T],
}
impl<'a, T: 'a> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next<b>(&'b mut self) -> Option<&'a mut T> {
        // omitted
    }
}

This design means you can call next many times on the iterator and keep the returned mutable references around. In this case it's safe because the returned references are non-overlapping.

Alternatively if the inner reference is not mutable, you are free to return the immutable reference in a non-linked way, because immutable references are allowed to alias.

// compiles!
struct Foo<'a>(&'a [u8]);

impl<'a> Foo<'a> {
    fn foo<'b>(&'b mut self) -> &'a [u8] {
        &self.0[0..1]
    }
}

playground

PS. Please make a new topic in the future, optionally linking to an old one if you feel it may be relevant.