Name Description Size
lib.rs Temporarily take ownership of a value at a mutable location, and replace it with a new value based on the old one. <p style="font-family: 'Fira Sans',sans-serif;padding:0.3em 0"><strong> <a href="https://crates.io/crates/replace_with">📦&nbsp;&nbsp;Crates.io</a>&nbsp;&nbsp;│&nbsp;&nbsp;<a href="https://github.com/alecmocatta/replace_with">📑&nbsp;&nbsp;GitHub</a>&nbsp;&nbsp;│&nbsp;&nbsp;<a href="https://constellation.zulipchat.com/#narrow/stream/213236-subprojects">💬&nbsp;&nbsp;Chat</a> </strong></p> 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](https://github.com/rust-lang/rfcs/pull/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`](https://github.com/Sgeo/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. The API also attempts to make slightly more explicit the behavior on panic – [`replace_with()`] accepts two closures such that aborting in the "standard case" where the mapping closure (`FnOnce(T) -> T`) panics (as [`take_mut::take()`](https://docs.rs/take_mut/0.2.2/take_mut/fn.take.html) does) is avoided. If the second closure (`FnOnce() -> T`) panics, however, then it does indeed abort. The "abort on first panic" behaviour is available with [`replace_with_or_abort()`]. # Example Consider this motivating example: ```compile_fail # use replace_with::*; 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: ``` # use replace_with::*; enum States { A(String), B(String), } # #[cfg(any(feature = "std", feature = "nightly"))] 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! 18677