replace_with
Temporarily take ownership of a value behind a mutable reference and replace it with a value mapped from the old one.
Repository Health
Technical Analysis
replace_with is a tiny Rust utility crate that solves a common ownership problem: mapping a value in place behind a &mut T when you need to move out of the old value to compute the new one. Its replace_with() function is like std::mem::replace(), except the replacement is produced by a closure that consumes the original value, which is exactly what Rust’s borrow checker normally forbids.
It is closely related to take_mut but uses Drop rather than std::panic::catch_unwind to handle unwinding, avoiding an optimization barrier and running significantly faster. The crate offers explicit control over panic behavior via a fallback closure or the abort-on-panic variant, and it supports no_std environments.
What You Get
- replace_with(place, default_closure, map_closure) for in-place mapping with a panic fallback
- replace_with_or_abort() for the simpler abort-on-panic behavior
- A faster alternative to take_mut that avoids catch_unwind’s optimization barrier
- Well-defined panic semantics: the mapping closure can panic without aborting when a fallback is given
- no_std support and an optional nightly feature for core::intrinsics::abort()
Common Use Cases
- Transitioning an enum state machine in place behind &mut self
- Replacing a value with one computed by consuming the old value
- Avoiding cannot move out of borrowed content errors without unsafe
- Working in no_std contexts where take_mut is unavailable or heavier
Under The Hood
Architecture - The crate is a single small module exposing a few free functions. replace_with reads the value out of the &mut T with ptr::read, hands ownership to the mapping closure, and ptr::writes the returned value back. To stay sound if the closure unwinds, it installs a Drop guard that runs a supplied fallback (or aborts) so the referenced location is never left uninitialized. This differs from take_mut, which relies on catch_unwind; using Drop avoids the extern “C” __rust_maybe_catch_panic optimization barrier.
Tech Stack - 100% Rust, no runtime dependencies. It is no_std-capable behind a default std feature, with an optional nightly feature that swaps the abort path to core::intrinsics::abort(). Distributed as the replace_with Cargo crate and documented on docs.rs.
Code Quality - Despite being tiny (~21 KB of Rust), the crate is careful about the subtle unsafe/unwind-safety it encapsulates, exposing a fully safe public API. It is mature and battle-tested (19M+ downloads) though largely in maintenance mode with low recent activity.
API Design - The API is minimal and purpose-built: replace_with(place, default, map) for full control over panic behavior and replace_with_or_abort(place, map) for the common case. The motivating enum-state-machine example in the README makes the intended usage immediately clear, keeping the learning curve very low.