4

The following code fails to compile because MutRef is not Copy. It can not be made copy because &'a mut i32 is not Copy. Is there any way give MutRef similar semantics to &'a mut i32?

The motivation for this is being able to package up a large set of function parameters into a struct so that they can be passed as a group instead of needing to be passed individually.

struct MutRef<'a> {
    v: &'a mut i32
}

fn wrapper_use(s: MutRef) {
}

fn raw_use(s: &mut i32) {
}

fn raw_ref() {
    let mut s: i32 = 9;
    let q = &mut s;
    raw_use(q);
    raw_use(q);

}

fn wrapper() {
    let mut s: i32 = 9;
    let q = MutRef{ v: &mut s };
    wrapper_use(q);
    wrapper_use(q);
}
Jeff Muizelaar
  • 574
  • 2
  • 8
  • 1
    [Relevant Reddit thread](https://www.reddit.com/r/rust/comments/46qwjv/why_can_i_use_an_mut_reference_twice/). – SCappella Oct 26 '19 at 03:15

1 Answers1

3

No.

The name for this feature is "implicit reborrowing" and it happens when you pass a &mut reference where the compiler expects a &mut reference of a possibly different lifetime. The compiler only implicitly reborrows when the actual type and the expected type are both &mut references. It does not work with generic arguments or structs that contain &mut references. There is no way in current Rust to make a custom type that can be implicitly reborrowed. There is an open issue about this limitation dating from 2015, but so far nobody has proposed any way to lift it.

You can always implement your own method to explicitly reborrow:

impl<'a> MutRef<'a> {
    // equivalent to fn reborrow(&mut self) -> MutRef<'_>
    fn reborrow<'b>(&'b mut self) -> MutRef<'b> {
        MutRef {v: self.v}
    }
}

fn wrapper() {
    let mut s: i32 = 9;
    let mut q = MutRef{ v: &mut s };
    wrapper_use(q.reborrow());  // does not move q
    wrapper_use(q);             // moves q
}

See also

trent
  • 25,033
  • 7
  • 51
  • 90