Skip to content

Commit 8e5fe55

Browse files
committed
improve comments and naming
1 parent 6464586 commit 8e5fe55

File tree

1 file changed

+56
-25
lines changed

1 file changed

+56
-25
lines changed

library/alloc/src/vec.rs

+56-25
Original file line numberDiff line numberDiff line change
@@ -2014,7 +2014,7 @@ impl<T, I: SliceIndex<[T]>> IndexMut<I> for Vec<T> {
20142014
impl<T> FromIterator<T> for Vec<T> {
20152015
#[inline]
20162016
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
2017-
<Self as SpecFrom<T, I::IntoIter>>::from_iter(iter.into_iter())
2017+
<Self as SpecFromIter<T, I::IntoIter>>::from_iter(iter.into_iter())
20182018
}
20192019
}
20202020

@@ -2096,18 +2096,39 @@ impl<T> Extend<T> for Vec<T> {
20962096
}
20972097
}
20982098

2099-
// Specialization trait used for Vec::from_iter
2100-
trait SpecFrom<T, I> {
2099+
/// Specialization trait used for Vec::from_iter
2100+
///
2101+
/// ## The delegation graph:
2102+
///
2103+
/// ```text
2104+
/// +-------------+
2105+
/// |FromIterator |
2106+
/// +-+-----------+
2107+
/// |
2108+
/// v
2109+
/// +-+-------------------------------+ +---------------------+
2110+
/// |SpecFromIter +---->+SpecFromIterNested |
2111+
/// |where I: | | |where I: |
2112+
/// | Iterator (default)----------+ | | Iterator (default) |
2113+
/// | vec::IntoIter | | | TrustedLen |
2114+
/// | SourceIterMarker---fallback-+ | | |
2115+
/// | slice::Iter | | |
2116+
/// | Iterator<Item = &Clone> | +---------------------+
2117+
/// +---------------------------------+
2118+
///
2119+
/// ```
2120+
trait SpecFromIter<T, I> {
21012121
fn from_iter(iter: I) -> Self;
21022122
}
21032123

2104-
// Another specialization trait for Vec::from_iter
2105-
// necessary to manually prioritize overlapping specializations
2106-
trait SpecFromNested<T, I> {
2124+
/// Another specialization trait for Vec::from_iter
2125+
/// necessary to manually prioritize overlapping specializations
2126+
/// see [`SpecFromIter`] for details.
2127+
trait SpecFromIterNested<T, I> {
21072128
fn from_iter(iter: I) -> Self;
21082129
}
21092130

2110-
impl<T, I> SpecFromNested<T, I> for Vec<T>
2131+
impl<T, I> SpecFromIterNested<T, I> for Vec<T>
21112132
where
21122133
I: Iterator<Item = T>,
21132134
{
@@ -2136,7 +2157,7 @@ where
21362157
}
21372158
}
21382159

2139-
impl<T, I> SpecFromNested<T, I> for Vec<T>
2160+
impl<T, I> SpecFromIterNested<T, I> for Vec<T>
21402161
where
21412162
I: TrustedLen<Item = T>,
21422163
{
@@ -2149,12 +2170,12 @@ where
21492170
}
21502171
}
21512172

2152-
impl<T, I> SpecFrom<T, I> for Vec<T>
2173+
impl<T, I> SpecFromIter<T, I> for Vec<T>
21532174
where
21542175
I: Iterator<Item = T>,
21552176
{
21562177
default fn from_iter(iterator: I) -> Self {
2157-
SpecFromNested::from_iter(iterator)
2178+
SpecFromIterNested::from_iter(iterator)
21582179
}
21592180
}
21602181

@@ -2182,18 +2203,21 @@ impl<T> Drop for InPlaceDrop<T> {
21822203
}
21832204
}
21842205

2185-
impl<T> SpecFrom<T, IntoIter<T>> for Vec<T> {
2206+
impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
21862207
fn from_iter(iterator: IntoIter<T>) -> Self {
21872208
// A common case is passing a vector into a function which immediately
21882209
// re-collects into a vector. We can short circuit this if the IntoIter
21892210
// has not been advanced at all.
2190-
// We can also reuse the memory and move the data to the front if
2191-
// allocating a new vector and moving to it would result in the same capacity
2192-
let non_zero_offset = iterator.buf.as_ptr() as *const _ != iterator.ptr;
2193-
if !non_zero_offset || iterator.len() >= iterator.cap / 2 {
2211+
// When it has been advanced We can also reuse the memory and move the data to the front.
2212+
// But we only do so when the resulting Vec wouldn't have more unused capacity
2213+
// than creating it through the generic FromIterator implementation would. That limitation
2214+
// is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
2215+
// But it is a conservative choice.
2216+
let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
2217+
if !has_advanced || iterator.len() >= iterator.cap / 2 {
21942218
unsafe {
21952219
let it = ManuallyDrop::new(iterator);
2196-
if non_zero_offset {
2220+
if has_advanced {
21972221
ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
21982222
}
21992223
return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
@@ -2224,6 +2248,12 @@ fn write_in_place_with_drop<T>(
22242248
}
22252249
}
22262250

2251+
/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the
2252+
/// source allocation, i.e. executing the pipeline in place.
2253+
///
2254+
/// The SourceIter parent trait is necessary for the specializing function to access the allocation
2255+
/// which is to be reused. But it is not sufficient for the specialization to be valid. See
2256+
/// additional bounds on the impl.
22272257
#[rustc_unsafe_specialization_marker]
22282258
trait SourceIterMarker: SourceIter<Source: AsIntoIter> {}
22292259

@@ -2235,7 +2265,7 @@ trait SourceIterMarker: SourceIter<Source: AsIntoIter> {}
22352265
// several other specializations already depend on.
22362266
impl<T> SourceIterMarker for T where T: SourceIter<Source: AsIntoIter> + InPlaceIterable {}
22372267

2238-
impl<T, I> SpecFrom<T, I> for Vec<T>
2268+
impl<T, I> SpecFromIter<T, I> for Vec<T>
22392269
where
22402270
I: Iterator<Item = T> + SourceIterMarker,
22412271
{
@@ -2251,7 +2281,8 @@ where
22512281
|| mem::align_of::<T>()
22522282
!= mem::align_of::<<<I as SourceIter>::Source as AsIntoIter>::Item>()
22532283
{
2254-
return SpecFromNested::from_iter(iterator);
2284+
// fallback to more generic implementations
2285+
return SpecFromIterNested::from_iter(iterator);
22552286
}
22562287

22572288
let (src_buf, dst_buf, dst_end, cap) = unsafe {
@@ -2277,9 +2308,9 @@ where
22772308
debug_assert!(dst as *const _ <= src.ptr, "InPlaceIterable contract violation");
22782309

22792310
// drop any remaining values at the tail of the source
2280-
src.drop_in_place();
2311+
src.drop_remaining();
22812312
// but prevent drop of the allocation itself once IntoIter goes out of scope
2282-
src.forget_in_place();
2313+
src.forget_allocation();
22832314

22842315
let vec = unsafe {
22852316
let len = dst.offset_from(dst_buf) as usize;
@@ -2290,17 +2321,17 @@ where
22902321
}
22912322
}
22922323

2293-
impl<'a, T: 'a, I> SpecFrom<&'a T, I> for Vec<T>
2324+
impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
22942325
where
22952326
I: Iterator<Item = &'a T>,
22962327
T: Clone,
22972328
{
22982329
default fn from_iter(iterator: I) -> Self {
2299-
SpecFrom::from_iter(iterator.cloned())
2330+
SpecFromIter::from_iter(iterator.cloned())
23002331
}
23012332
}
23022333

2303-
impl<'a, T: 'a> SpecFrom<&'a T, slice::Iter<'a, T>> for Vec<T>
2334+
impl<'a, T: 'a> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T>
23042335
where
23052336
T: Copy,
23062337
{
@@ -2824,7 +2855,7 @@ impl<T> IntoIter<T> {
28242855
ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
28252856
}
28262857

2827-
fn drop_in_place(&mut self) {
2858+
fn drop_remaining(&mut self) {
28282859
if mem::needs_drop::<T>() {
28292860
unsafe {
28302861
ptr::drop_in_place(self.as_mut_slice());
@@ -2835,7 +2866,7 @@ impl<T> IntoIter<T> {
28352866

28362867
/// Relinquishes the backing allocation, equivalent to
28372868
/// `ptr::write(&mut self, Vec::new().into_iter())`
2838-
fn forget_in_place(&mut self) {
2869+
fn forget_allocation(&mut self) {
28392870
self.cap = 0;
28402871
self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
28412872
self.ptr = self.buf.as_ptr();

0 commit comments

Comments
 (0)