Here is a simple program that overwrites an enum variable with another variant with associated data, and then needs a reference to that associated data afterward. (A more realistic example would have associated data that can't easily be copied.)
fn choose_u64() -> u64 { 1234 }
#[derive(Debug)]
enum E {
V1(),
V2(u64)
}
fn main() {
// Set up some enum-typed variable.
let mut e = E::V1();
// Switch it to contain variant 2, with an associated value, and get a
// reference to that value.
e = E::V2(choose_u64());
let E::V2(n) = &e else {
panic!("Shouldn't get here");
};
println!("I emplaced: {n}");
}
Is there any better idiom for this that doesn't require boilerplate to convince the compiler that you checked for something that can never happen (the else panic branch)? I know you can do the same with a match
expression, but that is even more boilerplate. I'm hoping for some construct like std::variant::emplace
from C++, which provides the caller with a reference to the value they just emplaced.
As a secondary question that informs how important the first is: is the compiler likely in practice to actually generate any code for the impossible branch in a release build, or is it purely a syntactic annoyance?
I'm hoping for some construct like std::variant::emplace from C++, which provides the caller with a reference to the value they just emplaced.
AFAIK there's no such thing:
V2(u64)
as a unit, therefore even with a helper there is no real way to handle this case any other way than as a two-step, at most you can use unsafe APIs for the second step (see below).You could set a primitive representation for your enum to make sure they have a stable memory representation and retrieve the value pointer directly, but that's a bit...
As a secondary question that informs how important the first is: is the compiler likely in practice to actually generate any code for the impossible branch in a release build, or is it purely a syntactic annoyance?
If you plug your snippet into godbolt you'll see that with -O
it doesn't even reference the panic entry point, so I'd say it's mostly the latter.
Also FWIW in this case you should probably use unreachable!
. It's effectively an alias for panic!
(and will indeed panic) but it provides better classification for automated tooling, and hinting to readers.