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));

See also this article and the below crate.


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.