diff options
| author | bors <bors@rust-lang.org> | 2019-06-07 18:26:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-06-07 18:26:15 +0000 |
| commit | d132f544f9d74e3cc047ef211e57eae60b78e5c5 (patch) | |
| tree | 791d2fe11b49b7a14bba265fb1cdb41629e81282 | |
| parent | c8865d8e195813ade6b84434ac9f8850e7112d1a (diff) | |
| parent | 5a01b547078e45cc1a96a062334d8571f129ddc2 (diff) | |
| download | rust-d132f544f9d74e3cc047ef211e57eae60b78e5c5.tar.gz rust-d132f544f9d74e3cc047ef211e57eae60b78e5c5.zip | |
Auto merge of #61130 - jonhoo:mem-take, r=SimonSapin
Add std::mem::take as suggested in #61129 This PR implements #61129 by adding `std::mem::take`. The added function is equivalent to: ```rust std::mem::replace(dest, Default::default()) ``` This particular pattern is fairly common, especially when implementing `Future::poll`, where you often need to yield an owned value in `Async::Ready`. This change allows you to write ```rust return Async::Ready(std::mem::take(self.result)); ``` instead of ```rust return Async::Ready(std::mem::replace(self.result, Vec::new())); ``` EDIT: Changed name from `take` to `swap_default`. EDIT: Changed name back to `take`.
| -rw-r--r-- | src/libcore/mem/mod.rs | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index b43ba6ac340..770d1ca8e75 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -503,6 +503,61 @@ pub fn swap<T>(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<i32> = 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<T> { buf: Vec<T> } +/// +/// impl<T> Buffer<T> { +/// fn get_and_reset(&mut self) -> Vec<T> { +/// // 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<T> { buf: Vec<T> } +/// impl<T> Buffer<T> { +/// fn get_and_reset(&mut self) -> Vec<T> { +/// mem::take(&mut self.buf) +/// } +/// } +/// ``` +/// +/// [`Clone`]: ../../std/clone/trait.Clone.html +#[inline] +#[unstable(feature = "mem_take", issue = "61129")] +pub fn take<T: Default>(dest: &mut T) -> T { + replace(dest, T::default()) +} + /// Moves `src` into the referenced `dest`, returning the previous `dest` value. /// /// Neither value is dropped. |
