From 5a01b547078e45cc1a96a062334d8571f129ddc2 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 24 May 2019 13:52:06 -0400 Subject: [PATCH] Add std::mem::take as suggested in #61129 The name `swap_default` was suggested but rejected. @SimonSapin observed that this operation isn't really a `swap` in the same sense as `mem::swap`; it is a `replace`. Since `replace_default` is a bit misleading, the "correct" name would be `replace_with_default`, which is quite verbose. @czipperz observed that we have precedence for using `take` to refer to methods that replace with `Default` in `Cell::take` and `Option::take`, so this reverts commit 99c00591c29b472c8a87c4a9342d0e0c508647a3 to return to the original `take` method name. The name `replace_with_default` was suggested, but was deemed too verbose, especially given that we use `take` for methods that replace with `Default` elsewhere. --- src/libcore/mem/mod.rs | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 91449f09936aa..c4d8e40a5e682 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -503,6 +503,61 @@ pub fn swap(x: &mut T, y: &mut T) { } } +/// Replace `dest` with the default value of `T`, and return the previous `dest` value. +/// +/// # Examples +/// +/// A simple example: +/// +/// ``` +/// use std::mem; +/// +/// let mut v: Vec = vec![1, 2]; +/// +/// let old_v = mem::take(&mut v); +/// assert_eq!(vec![1, 2], old_v); +/// assert!(v.is_empty()); +/// ``` +/// +/// `take` allows taking ownership of a struct field by replacing it with an "empty" value. +/// Without `take` you can run into issues like these: +/// +/// ```compile_fail,E0507 +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let buf = self.buf; +/// self.buf = Vec::new(); +/// buf +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset +/// `self.buf`. But `take` can be used to disassociate the original value of `self.buf` from +/// `self`, allowing it to be returned: +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::mem; +/// +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// mem::take(&mut self.buf) +/// } +/// } +/// ``` +/// +/// [`Clone`]: ../../std/clone/trait.Clone.html +#[inline] +#[unstable(feature = "mem_take", issue = "61129")] +pub fn take(dest: &mut T) -> T { + replace(dest, T::default()) +} + /// Moves `src` into the referenced `dest`, returning the previous `dest` value. /// /// Neither value is dropped.