diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index a6be81c91bbf1..881a4d1d2d1b3 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -45,6 +45,7 @@ #![feature(nonzero)] #![feature(pattern)] #![feature(placement_in)] +#![feature(placement_in_syntax)] #![feature(placement_new_protocol)] #![feature(shared)] #![feature(slice_patterns)] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 4f4eae67e37cd..416bd0efb332d 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -70,7 +70,7 @@ use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; use core::iter::FromIterator; use core::mem; -use core::ops::{Index, IndexMut}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer}; use core::ops; use core::ptr; use core::slice; @@ -699,16 +699,7 @@ impl Vec { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, value: T) { - // This will panic or abort if we would allocate > isize::MAX bytes - // or if the length increment would overflow for zero-sized types. - if self.len == self.buf.cap() { - self.buf.double(); - } - unsafe { - let end = self.as_mut_ptr().offset(self.len as isize); - ptr::write(end, value); - self.len += 1; - } + self <- value; } /// Removes the last element from a vector and returns it, or `None` if it @@ -1759,3 +1750,62 @@ impl<'a, T> Drop for Drain<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Drain<'a, T> {} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> Placer for &'a mut Vec { + type Place = BackPlace<'a, T>; + + fn make_place(self) -> BackPlace<'a, T> { + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if self.len == self.buf.cap() { + self.buf.double(); + } + + BackPlace { vec: self } + } +} + +/// A place for insertion at the back of a `Vec`. +/// +/// # Examples +/// +/// ``` +/// #![feature(placement_in_syntax)] +/// +/// let mut vec = vec![1, 2]; +/// &mut vec <- 3; +/// &mut vec <- 4; +/// assert_eq!(&vec, &[1, 2, 3, 4]); +/// ``` +#[must_use = "places do nothing unless written to with `<-` syntax"] +#[unstable(feature = "collection_placement", + reason = "struct name and placement protocol are subject to change", + issue = "30172")] +pub struct BackPlace<'a, T: 'a> { + vec: &'a mut Vec, +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> Place for BackPlace<'a, T> { + fn pointer(&mut self) -> *mut T { + unsafe { self.vec.as_mut_ptr().offset(self.vec.len as isize) } + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> InPlace for BackPlace<'a, T> { + type Owner = &'a mut T; + + unsafe fn finalize(mut self) -> &'a mut T { + let ptr = self.pointer(); + self.vec.len += 1; + &mut *ptr + } +} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 62fefaa10f677..5f0fc9ac17420 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -23,8 +23,11 @@ #![feature(iter_arith)] #![feature(map_entry_keys)] #![feature(pattern)] +#![feature(placement_in_syntax)] #![feature(rand)] +#![feature(recover)] #![feature(set_recovery)] +#![feature(std_panic)] #![feature(step_by)] #![feature(str_char)] #![feature(str_escape)] diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index ccdbf1092ff1e..365c6fc33eb41 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -11,6 +11,7 @@ use std::borrow::Cow; use std::iter::{FromIterator, repeat}; use std::mem::size_of; +use std::panic; use test::Bencher; @@ -495,6 +496,23 @@ fn test_cow_from() { } } +#[test] +fn test_placement() { + let mut vec = vec![1]; + assert_eq!(&mut vec <- 2, &2); + assert_eq!(vec.len(), 2); + assert_eq!(&mut vec <- 3, &3); + assert_eq!(vec.len(), 3); + assert_eq!(&vec, &[1, 2, 3]); +} + +#[test] +fn test_placement_panic() { + let mut vec = vec![1, 2, 3]; + let _ = panic::recover(panic::AssertRecoverSafe(|| { &mut vec <- panic!(); })); + assert_eq!(vec.len(), 3); +} + #[bench] fn bench_new(b: &mut Bencher) { b.iter(|| {