Crate replace_with

source ·
Expand description

Temporarily take ownership of a value at a mutable location, and replace it with a new value based on the old one.

Crates.ioRepo

This crate provides the function replace_with(), which is like std::mem::replace() except it allows the replacement value to be mapped from the original value.

See RFC 1736 for a lot of discussion as to its merits. It was never merged, and the desired ability to temporarily move out of &mut T doesn’t exist yet, so this crate is my interim solution.

It’s very akin to take_mut, though uses Drop instead of std::panic::catch_unwind() to react to unwinding, which avoids the optimisation barrier of calling the extern "C" __rust_maybe_catch_panic(). As such it’s up to ∞x faster. It’s also aesthetically a little prettier (I think).

Example

Consider this motivating example:

enum States {
	A(String),
	B(String),
}

impl States {
	fn poll(&mut self) {
		// error[E0507]: cannot move out of borrowed content
		*self = match *self {
		//            ^^^^^ cannot move out of borrowed content
			States::A(a) => States::B(a),
			States::B(a) => States::A(a),
		};
	}
}

Depending on context this can be quite tricky to work around. With this crate, however:

enum States {
	A(String),
	B(String),
}

impl States {
	fn poll(&mut self) {
		replace_with_or_abort(self, |self_| match self_ {
			States::A(a) => States::B(a),
			States::B(a) => States::A(a),
		});
	}
}

Huzzah!

Functions

Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one.
Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Aborts on panic.
Temporarily takes ownership of a value at a mutable location, and replace it with a new value based on the old one. Replaces with Default::default() on panic.