What is the idiomatic way to replace (in multiple steps) a struct field if the struct is behind a mutable reference?

An alternative which is very similar to the Updating one but doesn't require adding variants is to use the take_mut/replace_with crate. This allows you to temporarily move out of a reference and only after that put back something. This seems to perfectly fit your requirements. The only downside however is that it must put something back, if it can't then it must abort (not panic!)

1 Like

I agree with @isibboi that this is a deficiency of Rust's unique references. The only reason the straightforward code is not allowed by the type system is the potential for panic unwinding. If panics were to always abort, this wouldn't cause any unsafety and could be allowed.

The take_mut crate provides a solution to this exact problem.

It works by making all panics abort if they happen during the time you're replacing the object to which you have a unique reference.

impl AOrB {
    fn a_to_b(&mut self) {
        take_mut::take(self, |take_self| match take_self {
            AOrB::A(a) => AOrB::B(B {
                data: a.data,
                some_more_fields: "".into(),
            }),
            _ => panic!(),
        })
    }
}
3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.