Suppose your struct
consists of the following field:
pub struct Transaction{
items: Vec<String>,
amount: i32,
state: String
}
And you expose public interface to change the state
of Transaction
:
impl Transaction {
pub fn change_string(&mut self){
self.state = self.state.change_string()
}
}
In this case, if the method change_string()
on state
takes ownership, it won’t be working, erroring out:
Cannot move out of
self.state
which is behind a mutable reference move occurs becauseself.state
has typeString
, which does not implement theCopy
trait
The reason for that is quite simple. the change_string
method(your public interface) takes &mut
so according to the ownership tree rule, you can’t move the ownership of value but only change.
But the method change_string
you delegate to its field tries to take the ownership, thereby Rust compiler rejecting such an attempt.
Solution to this problem is quite simple yet requires understanding over idiomatic Rust.
Option<type>
pub struct Transaction{
items: Vec<String>,
amount: i32,
state: Option<String>
}
.take()
on Option<type>
impl Transaction {
pub fn change_string(&mut self){
if let Some(s) = self.state.take(){
self.state = Some(s.change_string())
}
}
}
So, what .take()
does is it takes the value of Option
and leaves it None
. As that counts as changing value, as opposed to taking ownership, the Rust compiler doesn’t complain.