Auto merge of #38551 - aidanhs:aphs-vec-in-place, r=brson
Implement placement-in protocol for `Vec` Follow-up of #32366 per comment at https://github.com/rust-lang/rust/issues/30172#issuecomment-268099009, updating to latest rust, leaving @apasel422 as author and putting myself as committer. I've removed the implementation of `push` in terms of place to make this PR more conservative.
This commit is contained in:
commit
3191886426
@ -45,6 +45,7 @@
|
||||
#![feature(nonzero)]
|
||||
#![feature(pattern)]
|
||||
#![feature(placement_in)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(placement_new_protocol)]
|
||||
#![feature(shared)]
|
||||
#![feature(slice_get_slice)]
|
||||
|
@ -77,7 +77,7 @@ use core::hash::{self, Hash};
|
||||
use core::intrinsics::{arith_offset, assume};
|
||||
use core::iter::{FromIterator, FusedIterator, TrustedLen};
|
||||
use core::mem;
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::ops::{InPlace, Index, IndexMut, Place, Placer};
|
||||
use core::ops;
|
||||
use core::ptr;
|
||||
use core::ptr::Shared;
|
||||
@ -1246,6 +1246,29 @@ impl<T: Clone> Vec<T> {
|
||||
pub fn extend_from_slice(&mut self, other: &[T]) {
|
||||
self.spec_extend(other.iter())
|
||||
}
|
||||
|
||||
/// Returns a place for insertion at the back of the `Vec`.
|
||||
///
|
||||
/// Using this method with placement syntax is equivalent to [`push`](#method.push),
|
||||
/// but may be more efficient.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(collection_placement)]
|
||||
/// #![feature(placement_in_syntax)]
|
||||
///
|
||||
/// let mut vec = vec![1, 2];
|
||||
/// vec.place_back() <- 3;
|
||||
/// vec.place_back() <- 4;
|
||||
/// assert_eq!(&vec, &[1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
pub fn place_back(&mut self) -> PlaceBack<T> {
|
||||
PlaceBack { vec: self }
|
||||
}
|
||||
}
|
||||
|
||||
// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
|
||||
@ -2119,3 +2142,52 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> {
|
||||
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, T> FusedIterator for Drain<'a, T> {}
|
||||
|
||||
/// A place for insertion at the back of a `Vec`.
|
||||
///
|
||||
/// See [`Vec::place_back`](struct.Vec.html#method.place_back) for details.
|
||||
#[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 PlaceBack<'a, T: 'a> {
|
||||
vec: &'a mut Vec<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> Placer<T> for PlaceBack<'a, T> {
|
||||
type Place = PlaceBack<'a, T>;
|
||||
|
||||
fn make_place(self) -> Self {
|
||||
// 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.vec.len == self.vec.buf.cap() {
|
||||
self.vec.buf.double();
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> Place<T> for PlaceBack<'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<T> for PlaceBack<'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
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#![feature(binary_heap_extras)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(btree_range)]
|
||||
#![feature(collection_placement)]
|
||||
#![feature(collections)]
|
||||
#![feature(collections_bound)]
|
||||
#![feature(const_fn)]
|
||||
@ -20,6 +21,7 @@
|
||||
#![feature(enumset)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(pattern)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(rand)]
|
||||
#![feature(repeat_str)]
|
||||
#![feature(step_by)]
|
||||
|
@ -12,6 +12,7 @@ use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::iter::{FromIterator, repeat};
|
||||
use std::mem::size_of;
|
||||
use std::panic;
|
||||
use std::vec::{Drain, IntoIter};
|
||||
|
||||
use test::Bencher;
|
||||
@ -615,6 +616,24 @@ fn assert_covariance() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement() {
|
||||
let mut vec = vec![1];
|
||||
assert_eq!(vec.place_back() <- 2, &2);
|
||||
assert_eq!(vec.len(), 2);
|
||||
assert_eq!(vec.place_back() <- 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];
|
||||
fn mkpanic() -> usize { panic!() }
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
|
||||
assert_eq!(vec.len(), 3);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_new(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
|
Loading…
Reference in New Issue
Block a user