Skip to content

Commit

Permalink
refactor: moved SpecFromIterNested to spec_from_iter_nested.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
DeveloperC286 committed Dec 29, 2020
1 parent 9e08ce7 commit 56d82b3
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 52 deletions.
56 changes: 4 additions & 52 deletions library/alloc/src/vec/mod.rs
Expand Up @@ -117,6 +117,10 @@ use self::in_place_drop::InPlaceDrop;

mod in_place_drop;

use self::spec_from_iter_nested::SpecFromIterNested;

mod spec_from_iter_nested;

/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
///
/// # Examples
Expand Down Expand Up @@ -2176,58 +2180,6 @@ trait SpecFromIter<T, I> {
fn from_iter(iter: I) -> Self;
}

/// Another specialization trait for Vec::from_iter
/// necessary to manually prioritize overlapping specializations
/// see [`SpecFromIter`] for details.
trait SpecFromIterNested<T, I> {
fn from_iter(iter: I) -> Self;
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
I: Iterator<Item = T>,
{
default fn from_iter(mut iterator: I) -> Self {
// Unroll the first iteration, as the vector is going to be
// expanded on this iteration in every case when the iterable is not
// empty, but the loop in extend_desugared() is not going to see the
// vector being full in the few subsequent loop iterations.
// So we get better branch prediction.
let mut vector = match iterator.next() {
None => return Vec::new(),
Some(element) => {
let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(lower.saturating_add(1));
unsafe {
ptr::write(vector.as_mut_ptr(), element);
vector.set_len(1);
}
vector
}
};
// must delegate to spec_extend() since extend() itself delegates
// to spec_from for empty Vecs
<Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
vector
}
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
I: TrustedLen<Item = T>,
{
fn from_iter(iterator: I) -> Self {
let mut vector = match iterator.size_hint() {
(_, Some(upper)) => Vec::with_capacity(upper),
_ => Vec::new(),
};
// must delegate to spec_extend() since extend() itself delegates
// to spec_from for empty Vecs
vector.spec_extend(iterator);
vector
}
}

impl<T, I> SpecFromIter<T, I> for Vec<T>
where
I: Iterator<Item = T>,
Expand Down
56 changes: 56 additions & 0 deletions library/alloc/src/vec/spec_from_iter_nested.rs
@@ -0,0 +1,56 @@
use core::ptr::{self};
use core::iter::{TrustedLen};

use super::{Vec, SpecExtend};

/// Another specialization trait for Vec::from_iter
/// necessary to manually prioritize overlapping specializations
/// see [`SpecFromIter`] for details.
pub(super) trait SpecFromIterNested<T, I> {
fn from_iter(iter: I) -> Self;
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
I: Iterator<Item = T>,
{
default fn from_iter(mut iterator: I) -> Self {
// Unroll the first iteration, as the vector is going to be
// expanded on this iteration in every case when the iterable is not
// empty, but the loop in extend_desugared() is not going to see the
// vector being full in the few subsequent loop iterations.
// So we get better branch prediction.
let mut vector = match iterator.next() {
None => return Vec::new(),
Some(element) => {
let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(lower.saturating_add(1));
unsafe {
ptr::write(vector.as_mut_ptr(), element);
vector.set_len(1);
}
vector
}
};
// must delegate to spec_extend() since extend() itself delegates
// to spec_from for empty Vecs
<Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
vector
}
}

impl<T, I> SpecFromIterNested<T, I> for Vec<T>
where
I: TrustedLen<Item = T>,
{
fn from_iter(iterator: I) -> Self {
let mut vector = match iterator.size_hint() {
(_, Some(upper)) => Vec::with_capacity(upper),
_ => Vec::new(),
};
// must delegate to spec_extend() since extend() itself delegates
// to spec_from for empty Vecs
vector.spec_extend(iterator);
vector
}
}

0 comments on commit 56d82b3

Please sign in to comment.