Reputation: 13
When using a match
to modify a mutable variable, I haven't found a way to use match
in a way that is guaranteed to be non-exhaustive and not requiring clone
.
struct Stuff {
num: u32,
thing: bool,
}
enum Bar {
Nothing,
SomeStuff(Stuff),
AlsoNothing,
}
fn main() {
let mut things = vec![Bar::SomeStuff(Stuff {
num: 2,
thing: false,
})];
for x in things.iter_mut() {
*x = match *x {
Bar::Nothing => Bar::AlsoNothing,
Bar::AlsoNothing => Bar::SomeStuff(Stuff {
num: 3,
thing: true,
}),
Bar::SomeStuff(thing) => panic!("not sure"),
}
}
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:19:20
|
19 | *x = match *x {
| ^^ cannot move out of borrowed content
...
25 | Bar::SomeStuff(thing) => panic!("not sure"),
| ----- hint: to prevent move, use `ref thing` or `ref mut thing`
My intent is to write Bar::SomeStuff(thing) => Bar::SomeStuff(thing)
and effectively leave it unchanged, but I cannot move through with a borrow or a reference.
Bar::SomeStuff(thing.clone())
could work, but copying a big struct could be very expensive.
Removing the *x =
and changing to ()
could also work, but I am only returning a Bar
enum so having the compiler check the return type is something I hope to keep.
Upvotes: 1
Views: 575
Reputation: 13450
If you want to pass a value unchanged, just capture the match with a variable and pass that back, e.g.
fn foo(a: u32) -> u32 {
match a {
0 => 1,
1 => 2,
e => e,
}
}
In your case, I would move the variable assignment into the match arms
for x in things.iter_mut() {
match x {
Bar::Nothing => *x = Bar::AlsoNothing,
Bar::AlsoNothing => *x = Bar::SomeStuff(Stuff { num: 3, thing: true }),
_ => {},
}
}
Upvotes: 2