Skip to content

Commit

Permalink
Rollup merge of rust-lang#61130 - jonhoo:mem-take, r=SimonSapin
Browse files Browse the repository at this point in the history
Add std::mem::take as suggested in rust-lang#61129

This PR implements rust-lang#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`.
  • Loading branch information
Centril committed Jun 7, 2019
2 parents c8865d8 + 5a01b54 commit 20d3c86
Showing 1 changed file with 55 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/libcore/mem/mod.rs
Expand Up @@ -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.
Expand Down

0 comments on commit 20d3c86

Please sign in to comment.