Skip to content

Commit d24a277

Browse files
committed
refactor: moving SpecFromIter into spec_from_iter.rs
1 parent 56d82b3 commit d24a277

File tree

2 files changed

+102
-92
lines changed

2 files changed

+102
-92
lines changed

library/alloc/src/vec/mod.rs

Lines changed: 4 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ use self::spec_from_iter_nested::SpecFromIterNested;
121121

122122
mod spec_from_iter_nested;
123123

124+
use self::spec_from_iter::SpecFromIter;
125+
126+
mod spec_from_iter;
127+
124128
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
125129
///
126130
/// # Examples
@@ -2156,98 +2160,6 @@ impl<T, A: Allocator> Extend<T> for Vec<T, A> {
21562160
}
21572161
}
21582162

2159-
/// Specialization trait used for Vec::from_iter
2160-
///
2161-
/// ## The delegation graph:
2162-
///
2163-
/// ```text
2164-
/// +-------------+
2165-
/// |FromIterator |
2166-
/// +-+-----------+
2167-
/// |
2168-
/// v
2169-
/// +-+-------------------------------+ +---------------------+
2170-
/// |SpecFromIter +---->+SpecFromIterNested |
2171-
/// |where I: | | |where I: |
2172-
/// | Iterator (default)----------+ | | Iterator (default) |
2173-
/// | vec::IntoIter | | | TrustedLen |
2174-
/// | SourceIterMarker---fallback-+ | | |
2175-
/// | slice::Iter | | |
2176-
/// | Iterator<Item = &Clone> | +---------------------+
2177-
/// +---------------------------------+
2178-
/// ```
2179-
trait SpecFromIter<T, I> {
2180-
fn from_iter(iter: I) -> Self;
2181-
}
2182-
2183-
impl<T, I> SpecFromIter<T, I> for Vec<T>
2184-
where
2185-
I: Iterator<Item = T>,
2186-
{
2187-
default fn from_iter(iterator: I) -> Self {
2188-
SpecFromIterNested::from_iter(iterator)
2189-
}
2190-
}
2191-
2192-
impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
2193-
fn from_iter(iterator: IntoIter<T>) -> Self {
2194-
// A common case is passing a vector into a function which immediately
2195-
// re-collects into a vector. We can short circuit this if the IntoIter
2196-
// has not been advanced at all.
2197-
// When it has been advanced We can also reuse the memory and move the data to the front.
2198-
// But we only do so when the resulting Vec wouldn't have more unused capacity
2199-
// than creating it through the generic FromIterator implementation would. That limitation
2200-
// is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
2201-
// But it is a conservative choice.
2202-
let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
2203-
if !has_advanced || iterator.len() >= iterator.cap / 2 {
2204-
unsafe {
2205-
let it = ManuallyDrop::new(iterator);
2206-
if has_advanced {
2207-
ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
2208-
}
2209-
return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
2210-
}
2211-
}
2212-
2213-
let mut vec = Vec::new();
2214-
// must delegate to spec_extend() since extend() itself delegates
2215-
// to spec_from for empty Vecs
2216-
vec.spec_extend(iterator);
2217-
vec
2218-
}
2219-
}
2220-
2221-
impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
2222-
where
2223-
I: Iterator<Item = &'a T>,
2224-
T: Clone,
2225-
{
2226-
default fn from_iter(iterator: I) -> Self {
2227-
SpecFromIter::from_iter(iterator.cloned())
2228-
}
2229-
}
2230-
2231-
// This utilizes `iterator.as_slice().to_vec()` since spec_extend
2232-
// must take more steps to reason about the final capacity + length
2233-
// and thus do more work. `to_vec()` directly allocates the correct amount
2234-
// and fills it exactly.
2235-
impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
2236-
#[cfg(not(test))]
2237-
fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
2238-
iterator.as_slice().to_vec()
2239-
}
2240-
2241-
// HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
2242-
// required for this method definition, is not available. Instead use the
2243-
// `slice::to_vec` function which is only available with cfg(test)
2244-
// NB see the slice::hack module in slice.rs for more information
2245-
#[cfg(test)]
2246-
fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
2247-
crate::slice::to_vec(iterator.as_slice(), Global)
2248-
}
2249-
}
2250-
22512163
// Specialization trait used for Vec::extend
22522164
trait SpecExtend<T, I> {
22532165
fn spec_extend(&mut self, iter: I);
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use crate::alloc::Global;
2+
use core::mem::{ManuallyDrop};
3+
use core::ptr::{self};
4+
use core::slice::{self};
5+
6+
use super::{Vec, IntoIter, SpecFromIterNested, SpecExtend};
7+
8+
/// Specialization trait used for Vec::from_iter
9+
///
10+
/// ## The delegation graph:
11+
///
12+
/// ```text
13+
/// +-------------+
14+
/// |FromIterator |
15+
/// +-+-----------+
16+
/// |
17+
/// v
18+
/// +-+-------------------------------+ +---------------------+
19+
/// |SpecFromIter +---->+SpecFromIterNested |
20+
/// |where I: | | |where I: |
21+
/// | Iterator (default)----------+ | | Iterator (default) |
22+
/// | vec::IntoIter | | | TrustedLen |
23+
/// | SourceIterMarker---fallback-+ | | |
24+
/// | slice::Iter | | |
25+
/// | Iterator<Item = &Clone> | +---------------------+
26+
/// +---------------------------------+
27+
/// ```
28+
pub(super) trait SpecFromIter<T, I> {
29+
fn from_iter(iter: I) -> Self;
30+
}
31+
32+
impl<T, I> SpecFromIter<T, I> for Vec<T>
33+
where
34+
I: Iterator<Item = T>,
35+
{
36+
default fn from_iter(iterator: I) -> Self {
37+
SpecFromIterNested::from_iter(iterator)
38+
}
39+
}
40+
41+
impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
42+
fn from_iter(iterator: IntoIter<T>) -> Self {
43+
// A common case is passing a vector into a function which immediately
44+
// re-collects into a vector. We can short circuit this if the IntoIter
45+
// has not been advanced at all.
46+
// When it has been advanced We can also reuse the memory and move the data to the front.
47+
// But we only do so when the resulting Vec wouldn't have more unused capacity
48+
// than creating it through the generic FromIterator implementation would. That limitation
49+
// is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
50+
// But it is a conservative choice.
51+
let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
52+
if !has_advanced || iterator.len() >= iterator.cap / 2 {
53+
unsafe {
54+
let it = ManuallyDrop::new(iterator);
55+
if has_advanced {
56+
ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
57+
}
58+
return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
59+
}
60+
}
61+
62+
let mut vec = Vec::new();
63+
// must delegate to spec_extend() since extend() itself delegates
64+
// to spec_from for empty Vecs
65+
vec.spec_extend(iterator);
66+
vec
67+
}
68+
}
69+
70+
impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
71+
where
72+
I: Iterator<Item = &'a T>,
73+
T: Clone,
74+
{
75+
default fn from_iter(iterator: I) -> Self {
76+
SpecFromIter::from_iter(iterator.cloned())
77+
}
78+
}
79+
80+
// This utilizes `iterator.as_slice().to_vec()` since spec_extend
81+
// must take more steps to reason about the final capacity + length
82+
// and thus do more work. `to_vec()` directly allocates the correct amount
83+
// and fills it exactly.
84+
impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
85+
#[cfg(not(test))]
86+
fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
87+
iterator.as_slice().to_vec()
88+
}
89+
90+
// HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
91+
// required for this method definition, is not available. Instead use the
92+
// `slice::to_vec` function which is only available with cfg(test)
93+
// NB see the slice::hack module in slice.rs for more information
94+
#[cfg(test)]
95+
fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
96+
crate::slice::to_vec(iterator.as_slice(), Global)
97+
}
98+
}

0 commit comments

Comments
 (0)