Edit: added a second part of the question below.
I am getting the error "borrow of moved value" here, but the thing being moved is an &mut Containee, so I didn't expect it to cause a problem. The similar portion in the commented-out code just under it feels like it's doing basically the same thing. Can someone explain to me why the commented-out portion works, but the uncommented portion doesn't?
struct Container<'c>(&'c mut Containee);
enum Containee {
A(u32),
B(u32),
}
fn main() {
let mut a = Containee::A(5);
let container = Container(&mut a);
match container {
Container(inner @ Containee::A(num)) => {
*inner = Containee::B(*num);
}
/* But this works
Container(inner) => {
if let Containee::A(num) = inner {
*inner = Containee::B(*num);
}
}
*/
_ => {}
}
}
This produces the following error. I tried following all the suggestions around explicitly binding the subpattern in different ways (even though they didn't seem likely to help), and indeed they didn't end up helping.
error: borrow of moved value
--> src\main.rs:13:19
|
13 | Container(inner @ Containee::A(num)) => {
| ^^^^^ --- value borrowed here after move
| |
| value moved into `inner` here
| move occurs because `inner` has type `&mut Containee`, which does not implement the `Copy` trait
|
help: borrow this binding in the pattern to avoid moving the value
|
13 | Container(ref inner @ Containee::A(num)) => {
| +++
Edit: thank you for the responses so far. In my actual use case, Containee holds something that isn't Copy, namely a String. The commented-out "if let" method works for that, but not the subpattern match, even the suggested fix in the answer.
struct Container<'c>(&'c mut Containee);
enum Containee {
A(String),
B(String),
}
fn main() {
let mut a = Containee::A(String::from("hi"));
let container = Container(&mut a);
match container {
Container(inner @ &mut Containee::A(data)) => {
*inner = Containee::B(data.clone());
}
/* But this works
Container(inner) => {
if let Containee::A(data) = inner {
*inner = Containee::B(data.clone());
}
}
*/
_ => {}
}
}
I know that inner is overwritten completely without anything other than the bound variable data being read. Is there a way to convince Rust about that too?
I get this error:
error[E0507]: cannot move out of `container` as enum variant `A` which is behind a mutable reference
--> src\main.rs:12:11
|
12 | match container {
| ^^^^^^^^^
13 | Container(inner @ &mut Containee::A(data)) => {
| ----
| |
| data moved here
| move occurs because `data` has type `String`, which does not implement the `Copy` trait
|
help: consider removing the mutable borrow
|
13 - Container(inner @ &mut Containee::A(data)) => {
13 + Container(inner @ Containee::A(data)) => {
|
Container(inner @ &mut Containee::A(num))works: playground.