I wrote a binary tree of i32. I want to change its root node to left node. But always failed. How to do it?
fn left(&mut self) -> Result<(), Error> {
match self.root.as_mut() {
Some(root) => match root.left {
Some(left) => {
self.root = Some(left); // this line always failed
return Ok(());
}
None => {
return Err(Error::NotFound);
}
},
None => {
return Err(Error::EmptyTree);
}
}
}
self.root = Some(left) I think it is easy to do this, but always failed.
error[E0507]: cannot move out of `root.left.0` which is behind a mutable reference
--> src/main.rs:120:33
|
120 | Some(root) => match root.left {
| ^^^^^^^^^ help: consider borrowing here: `&root.left`
121 | Some(left) => {
| ----
| |
| data moved here
| move occurs because `left` has type `Box<Node>`, which does not implement the `Copy` trait
For more information about this error, try `rustc --explain E0507`.
>Solution :
You can use std::mem::take, which allows taking things out of a mutable reference to them (replacing the pointed value with the default value of that type). That is, your function left can be rewritten:
use std::mem::take;
fn left(&mut self) -> Result<(), Error> {
let root = self.root.as_mut().ok_or(Error::EmptyTree)?;
let left = take(&mut root.left).ok_or(Error::NotFound)?;
*root = left;
Ok(())
}
Edit: turns out there is a method that does exactly that. I’ll leave my first snippet so that you understand what happens, but the following is probably more suitable in real code.
fn left(&mut self) -> Result<(), Error> {
let root = self.root.as_mut().ok_or(Error::EmptyTree)?;
let left = root.left.take().ok_or(Error::NotFound)?;
*root = left;
Ok(())
}