Rollup merge of #40731 - sfackler:vec-from-iter-spec, r=aturon
Specialize Vec::from_iter for vec::IntoIter It's fairly common to expose an API which takes an `IntoIterator` and immediately collects that into a vector. It's also common to buffer a bunch of items into a vector and then pass that into one of these APIs. If the iterator hasn't been advanced, we can make this `from_iter` simply reassemble the original `Vec` with no actual iteration or reallocation. r? @aturon
This commit is contained in:
commit
8ae1d444cb
@ -1563,7 +1563,7 @@ impl<T> ops::DerefMut for Vec<T> {
|
|||||||
impl<T> FromIterator<T> for Vec<T> {
|
impl<T> FromIterator<T> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
|
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
|
||||||
<Self as SpecExtend<_, _>>::from_iter(iter.into_iter())
|
<Self as SpecExtend<T, I::IntoIter>>::from_iter(iter.into_iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1631,7 +1631,7 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
|
|||||||
impl<T> Extend<T> for Vec<T> {
|
impl<T> Extend<T> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||||
self.spec_extend(iter.into_iter())
|
<Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1662,7 +1662,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
|
|||||||
vector
|
vector
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
vector.spec_extend(iterator);
|
<Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
|
||||||
vector
|
vector
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1674,7 +1674,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
|
|||||||
impl<T, I> SpecExtend<T, I> for Vec<T>
|
impl<T, I> SpecExtend<T, I> for Vec<T>
|
||||||
where I: TrustedLen<Item=T>,
|
where I: TrustedLen<Item=T>,
|
||||||
{
|
{
|
||||||
fn from_iter(iterator: I) -> Self {
|
default fn from_iter(iterator: I) -> Self {
|
||||||
let mut vector = Vec::new();
|
let mut vector = Vec::new();
|
||||||
vector.spec_extend(iterator);
|
vector.spec_extend(iterator);
|
||||||
vector
|
vector
|
||||||
@ -1706,6 +1706,27 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
|
||||||
|
fn from_iter(iterator: IntoIter<T>) -> Self {
|
||||||
|
// A common case is passing a vector into a function which immediately
|
||||||
|
// re-collects into a vector. We can short circuit this if the IntoIter
|
||||||
|
// has not been advanced at all.
|
||||||
|
if *iterator.buf == iterator.ptr as *mut T {
|
||||||
|
unsafe {
|
||||||
|
let vec = Vec::from_raw_parts(*iterator.buf as *mut T,
|
||||||
|
iterator.len(),
|
||||||
|
iterator.cap);
|
||||||
|
mem::forget(iterator);
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut vector = Vec::new();
|
||||||
|
vector.spec_extend(iterator);
|
||||||
|
vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
|
impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
|
||||||
where I: Iterator<Item=&'a T>,
|
where I: Iterator<Item=&'a T>,
|
||||||
T: Clone,
|
T: Clone,
|
||||||
|
@ -680,3 +680,19 @@ fn test_placement_panic() {
|
|||||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
|
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
|
||||||
assert_eq!(vec.len(), 3);
|
assert_eq!(vec.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_into_inner() {
|
||||||
|
let vec = vec![1, 2, 3];
|
||||||
|
let ptr = vec.as_ptr();
|
||||||
|
let vec = vec.into_iter().collect::<Vec<_>>();
|
||||||
|
assert_eq!(vec, [1, 2, 3]);
|
||||||
|
assert_eq!(vec.as_ptr(), ptr);
|
||||||
|
|
||||||
|
let ptr = &vec[1] as *const _;
|
||||||
|
let mut it = vec.into_iter();
|
||||||
|
it.next().unwrap();
|
||||||
|
let vec = it.collect::<Vec<_>>();
|
||||||
|
assert_eq!(vec, [2, 3]);
|
||||||
|
assert!(ptr != vec.as_ptr());
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user