No, this is not possible at all, since the size of each element can change when performing a mapping ( fn transform(u8) β u32
).
Even when the sizes are the same, it is not trivial.
In this case, you do not need to create a Dummy
variant because creating an empty String
is cheap; only 3 pointer size values ββand no heap allocation:
impl SomeType { fn transform(&mut self) { use SomeType::*; let old = std::mem::replace(self, VariantA(String::new()));
for x in &mut data { x.transform(); }
An alternative implementation that simply replaces String
:
impl SomeType { fn transform(&mut self) { use SomeType::*; *self = match self { VariantA(s) => { let s = std::mem::replace(s, String::new()); VariantB(s, 0) } VariantB(s, i) => { let s = std::mem::replace(s, String::new()); VariantB(s, 2 * *i) } }; } }
In general, yes, you need to create some kind of dummy value in order to do this in general and with safe code. Many times you can wrap the entire element in Option
and call Option::take
to achieve the same effect.
See also:
Why is it so hard?
Check out this proposed and now closed RFC for a variety of related discussions. My understanding of this RFC (and the difficulties behind it) is that there is a period of time when your value will have an indefinite value, which is unsafe . If panic happens at this moment, then when your value drops, you can cause undefined behavior, which is bad.
If your code panicked in a commented out line, then the self
value is a specific, known value. If it were some unknown value, deleting this line would try to delete this unknown value, and we returned to C. It is the purpose of the Dummy
value to always keep the value with a known value.
You even hinted at this (my selection):
I have to deal with SomeType::Dummy
everywhere in the code, although it should never be visible outside this loop.
This "must" is a problem. During a panic, this dummy value is visible.
See also:
Currently, the remote implementation of Vec::map_in_place
takes up nearly 175 lines of code, most of which are related to unsafe code and explains why it is really safe! Some boxes re-implemented this concept and tried to make it safe; You can see an example of Sebastian Redle's answer .