2

I am trying to create a mutable reference to a mutable reference, drop the outer reference, then reuse the inner reference. However, I always get some kind of error. Here is a somewhat minimized, very verbose example of the problem:

#[derive(Clone, Debug)]
struct NoCopy;

fn foo<'a>(vec: &'a mut Vec<NoCopy>) -> &'a mut NoCopy {
    {
        let try_first: Option<&'a mut NoCopy> = vec.first_mut();
        if let Some(first) = try_first {
            return first;
        }
    }

    vec.push(NoCopy);
    vec.first_mut().unwrap()
}

Playground

This gives the following errors:

error[E0499]: cannot borrow `*vec` as mutable more than once at a time
  --> src/lib.rs:12:5
   |
4  | fn foo<'a>(vec: &'a mut Vec<NoCopy>) -> &'a mut NoCopy {
   |        -- lifetime `'a` defined here
5  |     {
6  |         let try_first: Option<&'a mut NoCopy> = vec.first_mut();
   |                        ----------------------   --- first mutable borrow occurs here
   |                        |
   |                        type annotation requires that `*vec` is borrowed for `'a`
...
12 |     vec.push(NoCopy);
   |     ^^^ second mutable borrow occurs here

error[E0499]: cannot borrow `*vec` as mutable more than once at a time
  --> src/lib.rs:13:5
   |
4  | fn foo<'a>(vec: &'a mut Vec<NoCopy>) -> &'a mut NoCopy {
   |        -- lifetime `'a` defined here
5  |     {
6  |         let try_first: Option<&'a mut NoCopy> = vec.first_mut();
   |                        ----------------------   --- first mutable borrow occurs here
   |                        |
   |                        type annotation requires that `*vec` is borrowed for `'a`
...
13 |     vec.first_mut().unwrap()
   |     ^^^ second mutable borrow occurs here

No matter what I try, I cannot seem to get this to compile. I thought that this issue could be related to Why can't I reuse a &mut reference after passing it to a function that accepts a generic type?, but I cannot figure out how to apply the accepted solution to this problem. This makes me wonder if the error is actually correct behavior (i.e. my code would be unsafe), but I cannot seem to figure out any problem with the code.

How do I get this code to compile, or is the compiler error caused by an actual logical problem?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Coder-256
  • 5,212
  • 2
  • 23
  • 51
  • 1
    It's a weakness of the current implementation of the borrow checker. [The duplicate applied to your case](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=237389cf0b90cdbefcd2acde98b4c84b). – Shepmaster Mar 04 '20 at 18:16
  • @Shepmaster Thank you so much for finding this! I had a sinking feeling it was NLL. Unfortunately, my actual use case looks like `fn next_frame(&mut self) -> Option<&Frame>`. I'm trying to return `self.decoder.next_frame()` or else recreate `self.decoder`... time to refactor to I guess maybe `fn advance(&mut self)` and `fn frame(&self) -> Option<&Frame>`. – Coder-256 Mar 04 '20 at 18:36
  • That sounds suspiciously similar to [How do I write an iterator that returns references to itself?](https://stackoverflow.com/q/30422177/155423). If it's not, I'm not sure why this pattern wouldn't work. You'd switch `is_empty` for `is_none` perhaps. – Shepmaster Mar 04 '20 at 18:43
  • I am essentially creating a streaming iterator, but I don't think that has to do with the error. I think you were right the first time that the problem is due to NLL, the code should definitely be sound. There might be some workaround, but in my particular case I think it makes more sense to just return an owned value instead, even if I got this to work. – Coder-256 Mar 05 '20 at 20:04

0 Answers0