What I am trying to do:
enum Test {
Value1,
Value2,
Value3
}
fn main() {
let mut test_vec: Vec<Test> = Vec::new();
test_vec.push(Test::Value2);
if let Some(last) = test_vec.last() {
test_vec.push(*last);
}
//Wanted output: vector with [Test::Value2, Test::Value2]
}
I understand that when I call last(), it will return Option<&Test>
So it will borrow the test_vec till the end of the if-let block.
I tried the following without success:
if let Some(last) = test_vec.last().map(|v| v.clone()) {
test_vec.push(*last);
}
//and
let last = test_vec.last().unwrap().clone();
test_vec.push(*last);
When trying to figure out why the borrow checker complains it can be useful to identify the types involved.
If you type out:
let _: () = test_vec.last().map(|v| v.clone());
you get an error complaining that () and core::option::Option<&Test> are not the same type.
What's going on? Very simply put, if you clone an &Test you get an &Test, thus calling .map(|v| v.clone()) on a Option<&Test> gives an Option<&Test>. Obviously, it still borrows.
The same problem occurs with your next attempt, if you type out:
let _: () = test_vec.last().unwrap().clone();
you get an error complaining that () and &Test are not the same type.
By calling unwrap on an Option<&Test> you get an &Test which is then cloned into an &Test.
So, the problem is a lack of dereferencing. You need to dereference earlier, to avoid borrowing test_vec in Some(last):
if let Some(last) = test_vec.last().map(|v| (*v).clone()) {
test_vec.push(last);
}
of course, this does not work because Test does not implement clone. Once that is fixed (by #[derive(Clone)]), it compiles.
Since cloning from references is such a common need, there is a dedicated method on Option (and Iterator) called cloned:
if let Some(last) = test_vec.last().cloned() {
test_vec.push(last);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With