Skip to content

Commit 20d3c86

Browse files
authored
Rollup merge of rust-lang#61130 - jonhoo:mem-take, r=SimonSapin
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`.
2 parents c8865d8 + 5a01b54 commit 20d3c86

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

src/libcore/mem/mod.rs

+55
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,61 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
503503
}
504504
}
505505

506+
/// Replace `dest` with the default value of `T`, and return the previous `dest` value.
507+
///
508+
/// # Examples
509+
///
510+
/// A simple example:
511+
///
512+
/// ```
513+
/// use std::mem;
514+
///
515+
/// let mut v: Vec<i32> = vec![1, 2];
516+
///
517+
/// let old_v = mem::take(&mut v);
518+
/// assert_eq!(vec![1, 2], old_v);
519+
/// assert!(v.is_empty());
520+
/// ```
521+
///
522+
/// `take` allows taking ownership of a struct field by replacing it with an "empty" value.
523+
/// Without `take` you can run into issues like these:
524+
///
525+
/// ```compile_fail,E0507
526+
/// struct Buffer<T> { buf: Vec<T> }
527+
///
528+
/// impl<T> Buffer<T> {
529+
/// fn get_and_reset(&mut self) -> Vec<T> {
530+
/// // error: cannot move out of dereference of `&mut`-pointer
531+
/// let buf = self.buf;
532+
/// self.buf = Vec::new();
533+
/// buf
534+
/// }
535+
/// }
536+
/// ```
537+
///
538+
/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset
539+
/// `self.buf`. But `take` can be used to disassociate the original value of `self.buf` from
540+
/// `self`, allowing it to be returned:
541+
///
542+
/// ```
543+
/// # #![allow(dead_code)]
544+
/// use std::mem;
545+
///
546+
/// # struct Buffer<T> { buf: Vec<T> }
547+
/// impl<T> Buffer<T> {
548+
/// fn get_and_reset(&mut self) -> Vec<T> {
549+
/// mem::take(&mut self.buf)
550+
/// }
551+
/// }
552+
/// ```
553+
///
554+
/// [`Clone`]: ../../std/clone/trait.Clone.html
555+
#[inline]
556+
#[unstable(feature = "mem_take", issue = "61129")]
557+
pub fn take<T: Default>(dest: &mut T) -> T {
558+
replace(dest, T::default())
559+
}
560+
506561
/// Moves `src` into the referenced `dest`, returning the previous `dest` value.
507562
///
508563
/// Neither value is dropped.

0 commit comments

Comments
 (0)