debugrustCritical
Cannot move out of borrowed content / cannot move out of behind a shared reference
Viewed 0 times
borrowedmovebehindsharedoutcannotcontentreference
Problem
I don't understand the error
For example:
produces the error:
In newer versions of Rust, the error is
I solved it by cloning
I don't understand the error even after reading other posts like:
What is the origin of this kind of error?
cannot move out of borrowed content. I have received it many times and I have always solved it, but I've never understood why.For example:
for line in self.xslg_file.iter() {
self.buffer.clear();
for current_char in line.into_bytes().iter() {
self.buffer.push(*current_char as char);
}
println!("{}", line);
}produces the error:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:31:33
|
31 | for current_char in line.into_bytes().iter() {
| ^^^^ cannot move out of borrowed content
In newer versions of Rust, the error is
error[E0507]: cannot move out of *line which is behind a shared reference
--> src/main.rs:31:33
|
31 | for current_char in line.into_bytes().iter() {
| ^^^^ move occurs because *line has type std::string::String, which does not implement the Copy trait
I solved it by cloning
line:for current_char in line.clone().into_bytes().iter() {I don't understand the error even after reading other posts like:
- Can't borrow File from &mut self (error msg: cannot move out of borrowed content)
- Changing a node in a tree in Rust
What is the origin of this kind of error?
Solution
Let's look at the signature for
This takes
I don't know exactly what your
As you've found, one solution is to use
In the larger picture, this all has to do with the notion of ownership. Certain operations depend on owning the item, and other operations can get away with borrowing the object (perhaps mutably). A reference (
Why is it interesting to use
Transferring ownership is a useful concept in general - when I am done with something, someone else may have it. In Rust, it's a way to be more efficient. I can avoid allocating a copy, giving you one copy, then throwing away my copy. Ownership is also the most permissive state; if I own an object I can do with it as I wish.
Here's the code that I created to test with:
into_bytes:fn into_bytes(self) -> VecThis takes
self, not a reference to self (&self). That means that self will be consumed and won't be available after the call. In its place, you get a Vec. The prefix into_ is a common way of denoting methods like this.I don't know exactly what your
iter() method returns, but my guess is that it's an iterator over &String, that is, it returns references to a String but doesn't give you ownership of them. That means you cannot call a method that consumes the value.As you've found, one solution is to use
clone. This creates a duplicate object that you do own, and can call into_bytes on. As other commenters mention, you can also use as_bytes which takes &self, so it will work on a borrowed value. Which one you should use depends on your end goal for what you do with the pointer.In the larger picture, this all has to do with the notion of ownership. Certain operations depend on owning the item, and other operations can get away with borrowing the object (perhaps mutably). A reference (
&foo) does not grant ownership, it's just a borrow.Why is it interesting to use
self instead of &self in a function's arguments?Transferring ownership is a useful concept in general - when I am done with something, someone else may have it. In Rust, it's a way to be more efficient. I can avoid allocating a copy, giving you one copy, then throwing away my copy. Ownership is also the most permissive state; if I own an object I can do with it as I wish.
Here's the code that I created to test with:
struct IteratorOfStringReference(&'a String);
impl Iterator for IteratorOfStringReference {
type Item = &'a String;
fn next(&mut self) -> Option {
None
}
}
struct FileLikeThing {
string: String,
}
impl FileLikeThing {
fn iter(&self) -> IteratorOfStringReference {
IteratorOfStringReference(&self.string)
}
}
struct Dummy {
xslg_file: FileLikeThing,
buffer: String,
}
impl Dummy {
fn dummy(&mut self) {
for line in self.xslg_file.iter() {
self.buffer.clear();
for current_char in line.into_bytes().iter() {
self.buffer.push(*current_char as char);
}
println!("{}", line);
}
}
}
fn main() {}Code Snippets
fn into_bytes(self) -> Vec<u8>struct IteratorOfStringReference<'a>(&'a String);
impl<'a> Iterator for IteratorOfStringReference<'a> {
type Item = &'a String;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
struct FileLikeThing {
string: String,
}
impl FileLikeThing {
fn iter(&self) -> IteratorOfStringReference {
IteratorOfStringReference(&self.string)
}
}
struct Dummy {
xslg_file: FileLikeThing,
buffer: String,
}
impl Dummy {
fn dummy(&mut self) {
for line in self.xslg_file.iter() {
self.buffer.clear();
for current_char in line.into_bytes().iter() {
self.buffer.push(*current_char as char);
}
println!("{}", line);
}
}
}
fn main() {}Context
Stack Overflow Q#28158738, score: 168
Revisions (0)
No revisions yet.