It's frustrating this question was marked as duplicate, because this is another example of a dead-end trap for Rust newbies. It's very hard for a newbie to generalise from these specific answers, which means they just get stuck by the next instance (ref: me).
To provide a little of that generalisation, to help with general "cannot move out of" issues, consider why the issue arose in the first place. There are two primary reasons:
- You don't want to claim ownership of something.
- You want to claim ownership of something.
In the first case, you're inadvertently doing something that requires ownership. The solution then, is to find an alternative that doesn't require ownership. This is precisely the case outlined in this question and answer. Instead of into_bytes()
, which requires ownership since it consumes its input, substitute with as_bytes()
which will do the same thing without claiming ownership.
The reason the solution is not obvious is that the compiler has assumed you really did want to consume line
, and helpfully replaced it with *line
. Thus, it throws the misleading error, informing you the dereference didn't help. You're left scratching your head about how to fix the inability to move
, leading to band-aids like clone()
.
In fact, you never wanted to dereference in the first place, and just needed to find an alternative that worked with the borrow reference.
Now in the second case (which is the more relevant in the "duplicate" q&a I referenced at the top) the error is the same but you've inadvertently borrowed instead of claiming ownership. This is often the case when implementing a method, since methods typically employ a reference to self
rather than consuming it. Incidentally, this is entirely optional - a method can choose to consume rather than borrow self
, though I can't imagine this being very practical unless the method returns a Self
back.
In this second case, confusingly, a desperate clone()
will again appear to solve things, at least in the short term. But given the root causes, the root fix is a bit different. Since you actually do want to claim ownership (perhaps you're trying to drop data, or transfer it to another owner), you need to make that explicit.
In simple cases this might just be a matter of removing the &
from wherever you got the variable from - either the return value of a function you called, or as an argument to the current function.
Often you're not able to make that change though. Instead, you have to strip ownership away. But you can't just leave the current owner empty-handed - you need to leave them with something valid. The only way I know of to do this is to use one of take
, swap
or replace
from std::mem
. Arriving in 1.40, take
is by far the easiest - it simply gives the owner the Default
value, and gives you ownership of the current value. The swap
and replace
alternatives provide the previous owner with something else, which is particularly important if the type doesn't have a Default
.
Here's a before and after example:
pub struct SimpleLinkedList<T> {
head: Option<Box<Node<T>>>
}
pub struct Node<T> {
value: T,
next: Option<Box<Node<T>>>
}
impl<T> SimpleLinkedList<T> {
pub fn pop(&mut self) -> Option<T> {
if self.head.is_none() { return None; }
let value = self.head.unwrap().value;
self.head = self.head.unwrap().next;
return Some(value);
}
}
This throws the "cannot move out of self.head
which is behind a mutable reference" error, since unwrap()
consumes self
.
There's lots of ways to improve this, but for illustration purposes, this is all that is necessary:
use std::mem;
pub struct SimpleLinkedList<T> {
head: Option<Box<Node<T>>>
}
pub struct Node<T> {
value: T,
next: Option<Box<Node<T>>>
}
impl<T> SimpleLinkedList<T> {
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() { return None; }
let old_head = mem::take(&mut self.head);
let old_head_unwrapped = old_head.unwrap();
self.head = old_head_unwrapped.next;
return Some(old_head_unwrapped.value);
}
}
We're replacing the self.head
value anyway, so by calling take
on it we can claim ownership. We're then free to pass it to unwrap()
and subsequently overwrite the original self.head
.
So in conclusion, why do you get "cannot move out of borrowed content/reference"? Either because you only need to borrow and must ensure whatever you do never consumes, or because you actually want to consume and must take
ownership.
.bytes()
method.) – Mandatory.as_bytes()
– Defendantas_bytes()
without cloning. But I still don't understand why ? – CoquillageString
gets thebytes
method fromstr
. – Mandatory