I have an Option<&mut T>
and want to access the contained reference multiple times, like so:
fn f(a: Option<&mut i32>) {
if let Some(x) = a {
*x = 6;
}
// ...
if let Some(x) = a {
*x = 7;
}
}
fn main() {
let mut x = 5;
f(Some(&mut x));
}
That doesn't work, because if let Some(x) = a
moves the reference value out of the Option, and the second if let Some(x) = a
will result in a compiler error. Without the second if let ...
, this works flawlessly, so a
doesn't have to be mutable.
The following:
if let Some(ref x) = a {
**x = 6;
}
gives an error: "assignment into an immutable reference".
This would work:
fn f(mut a: Option<&mut i32>) {
if let Some(ref mut x) = a {
**x = 6;
}
if let Some(ref mut x) = a {
**x = 7;
}
}
The mut a
is necessary, otherwise I get an error "cannot borrow immutable anonymous field (a:std::prelude::v1::Some).0
as mutable". But this feels wrong: a
shouldn't have to be mutable, because I'm not modifying it (see above).
What's the correct solution?
My problem is different from the one in How to pass `Option<&mut ...>` to multiple function calls without causing move errors?. I want to mutably dereference the reference in an Option<&mut T>
multiple times, while the other one wants to pass an Option
to multiple function invocations. The solutions to the other question are not applicable to my situation.
What about this?
fn f(a: Option<&mut i32>) {
if let Some(&mut ref mut x) = a {
*x = 6;
}
// ...
if let Some(&mut ref mut x) = a {
*x = 7;
}
}
In this case, a
doesn't need to be mutable.
The &mut ref mut
feels a bit awkward, but it makes sense: first we remove a &mut
by destructuring and then take a mutable reference to the value again. It's more obvious when we don't use the Option
:
let mr: &mut Vec<u32> = &mut vec![];
{
let &mut ref mut a = mr;
a.push(3);
}
mr.push(4);
This also works. The third (special) line is equivalent to:
let a = &mut *mr ;
// ^^^----- this is an lvalue of type `Vec<u32>`
// ^^^^^^^^^^^^----- together it's of type `&mut Vec<u32>` again
In the Option
case, we can't use the &mut *X
version, but need to do all of it inside of the pattern. Thus the &mut ref mut x
.
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