alloc/vec/spec_from_iter.rs
1use core::mem::ManuallyDrop;
2use core::ptr::{self};
3
4use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec};
5
6/// Specialization trait used for Vec::from_iter
7///
8/// ## The delegation graph:
9///
10/// ```text
11/// +-------------+
12/// |FromIterator |
13/// +-+-----------+
14/// |
15/// v
16/// +-+---------------------------------+ +---------------------+
17/// |SpecFromIter +---->+SpecFromIterNested |
18/// |where I: | | |where I: |
19/// | Iterator (default)------------+ | | Iterator (default) |
20/// | vec::IntoIter | | | TrustedLen |
21/// | InPlaceCollect--(fallback to)-+ | +---------------------+
22/// +-----------------------------------+
23/// ```
24pub(super) trait SpecFromIter<T, I> {
25 fn from_iter(iter: I) -> Self;
26}
27
28impl<T, I> SpecFromIter<T, I> for Vec<T>
29where
30 I: Iterator<Item = T>,
31{
32 #[track_caller]
33 default fn from_iter(iterator: I) -> Self {
34 SpecFromIterNested::from_iter(iterator)
35 }
36}
37
38impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
39 #[track_caller]
40 fn from_iter(iterator: IntoIter<T>) -> Self {
41 // A common case is passing a vector into a function which immediately
42 // re-collects into a vector. We can short circuit this if the IntoIter
43 // has not been advanced at all.
44 // When it has been advanced We can also reuse the memory and move the data to the front.
45 // But we only do so when the resulting Vec wouldn't have more unused capacity
46 // than creating it through the generic FromIterator implementation would. That limitation
47 // is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
48 // But it is a conservative choice.
49 let has_advanced = iterator.buf != iterator.ptr;
50 if !has_advanced || iterator.len() >= iterator.cap / 2 {
51 unsafe {
52 let it = ManuallyDrop::new(iterator);
53 if has_advanced {
54 ptr::copy(it.ptr.as_ptr(), it.buf.as_ptr(), it.len());
55 }
56 return Vec::from_parts(it.buf, it.len(), it.cap);
57 }
58 }
59
60 let mut vec = Vec::new();
61 // must delegate to spec_extend() since extend() itself delegates
62 // to spec_from for empty Vecs
63 vec.spec_extend(iterator);
64 vec
65 }
66}