[SOLVED] Simple question about clone element in vecdeque (borrow and move)

I am implementing a queue, say MyQueue by wrapping VecDeque and then implementing certain methods that go directly to the VecDeque (I have to wrap it because the MyQueue will ultimately do other things, too.

I have almost everything worked out. I can push, pop, and iterate over the queue.

But, I also need to read the next element without popping it. I need to be able to read non-destructively. A typical peek().

When I tried to implement a peek() or front(), I ran into a problem, because VecDeque::front() returns an Option<&Message> with a reference instead of a value.

When I return a reference, I obviously can't use the MyQueue object after that. I get

error[E0502]: cannot borrow `queue` as immutable because it is also borrowed as mutable
   --> src/data/queue.rs:134:19
    |
132 |     let peek = queue.peek();
    |                ----- mutable borrow occurs here
133 |     assert_eq!("something3".to_string(), second.kind());
134 |     assert_eq!(2, queue.len());
    |                   ^^^^^ immutable borrow occurs here
135 |     }
    |     - mutable borrow ends here

That led me to thinking I should just clone the Message itself and return it, so I'm not returning a reference (borrow) from the MyQueue.

However, when I try this, I get a cannot move out of borrowed content.

Here is the relevant code:

impl StdQueue {
    fn peek(&mut self) -> Option<Message> {
       let r = self.queue.front();
       let a = r.unwrap();
       let me = *a.clone();
       Some(me)
   }
}

Which produces:

error[E0507]: cannot move out of borrowed content
  --> src/data/queue.rs:68:18
   |
68 |         let me = *a.clone();
   |                  ^^^^^^^^^^
   |                  |
   |                  cannot move out of borrowed content
   |                  help: consider using a reference instead: `&*a.clone()`

I'm really not sure where to go from here. How can I create a clone of the Message inside peek, and then return that value instead of a reference? Or, how can I return a reference, and continue to use the MyQueue object (I realize this is directly against the entire idea of safe borrowing, which is one thing that brought me to rust in the first place)

I'd also like to say that I have been really happy with Rust and especially this community so far. I've been asking a lot of questions and reading a lot. I'm excited to get to the point where I can actually contribute instead of just sponge. Thank you all for being patient :smile:

1 Like

Why does your peek() take &mut self rather than &self? If you took the latter, you’d be able to use &self methods while holding a reference.

For clone, you don’t need to dereference - just a.clone() is sufficient. But I’m not going to focus on this part because I don’t think you need clone :slight_smile:

1 Like

I think a lot of people don’t realize that they’re already contributing by virtue of asking questions :slight_smile:

I appreciate that. It's been an amazing community.

I was pretty sure I didn't need to dereference in order to clone(), but I was trying things. Thanks for the info. I was thinking it may have been cloning the reference?

If I did want to pass back a value instead of a reference, is there a quick solution to that? Or did I miss that in "The Book"?

There are some cases where you may inadvertently end up cloning a &T, and references (ie &T as a type) are trivially cloneable and copyable. Clippy has a lint for it even.

Given the VecDeque owns the values, you’d need to either take the value out of it (this is no longer a true peek) or clone it.

1 Like

Ah, that makes sense. Thanks for the help.