Mut refs and Either

If x: &mut Either<S, T> and I have a function of type f: FnOnce(S) -> T, is there a sound way to replace *x with Right(f(s)) when *x == Left(s)? Does this require unsafe?

More generally, if x: &mut T and f: FnOnce(T) -> T, is there a way to soundly replace *x with f(*x)?

Yes, but with a caveat: x must be valid at every point in time. The easiest way is to require Default:

use either::Either;
use std::mem::take;

pub fn replace_it<S: Default, T>(x: &mut Either<S, T>, f: impl FnOnce(S) -> T) {
    if let Either::Left(s) = x {
        let s = take(s);
        *x = Either::Right(f(s));
    }
}
3 Likes

See also this article and the below crate.

3 Likes

I'm specifically interested in the case where the Default bound doesn't apply.

This is still not possible to do soundly without providing something to act as a dummy intermediate value. The replace_with() function also requires a function to supply the default.

The take_mut crate does this without using a temporary value.

So does replace_with_or_abort(), but at the same cost – it will abort unconditionally upon panic. That's probably not great for general use.

I'm sorry, I didn't realize this was asked four days ago. Is there a FAQ for URLO (besides this)?

No,[1] but it's no problem to ask something asked before, even if recently; this isn't SO.


  1. nothing official anyway, just uncentralized topic-specific articles and the like ↩ī¸Ž

1 Like

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.