@@ -2014,7 +2014,7 @@ impl<T, I: SliceIndex<[T]>> IndexMut<I> for Vec<T> {
2014
2014
impl < T > FromIterator < T > for Vec < T > {
2015
2015
#[ inline]
2016
2016
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 ( ) )
2018
2018
}
2019
2019
}
2020
2020
@@ -2096,18 +2096,39 @@ impl<T> Extend<T> for Vec<T> {
2096
2096
}
2097
2097
}
2098
2098
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 > {
2101
2121
fn from_iter ( iter : I ) -> Self ;
2102
2122
}
2103
2123
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 > {
2107
2128
fn from_iter ( iter : I ) -> Self ;
2108
2129
}
2109
2130
2110
- impl < T , I > SpecFromNested < T , I > for Vec < T >
2131
+ impl < T , I > SpecFromIterNested < T , I > for Vec < T >
2111
2132
where
2112
2133
I : Iterator < Item = T > ,
2113
2134
{
@@ -2136,7 +2157,7 @@ where
2136
2157
}
2137
2158
}
2138
2159
2139
- impl < T , I > SpecFromNested < T , I > for Vec < T >
2160
+ impl < T , I > SpecFromIterNested < T , I > for Vec < T >
2140
2161
where
2141
2162
I : TrustedLen < Item = T > ,
2142
2163
{
@@ -2149,12 +2170,12 @@ where
2149
2170
}
2150
2171
}
2151
2172
2152
- impl < T , I > SpecFrom < T , I > for Vec < T >
2173
+ impl < T , I > SpecFromIter < T , I > for Vec < T >
2153
2174
where
2154
2175
I : Iterator < Item = T > ,
2155
2176
{
2156
2177
default fn from_iter ( iterator : I ) -> Self {
2157
- SpecFromNested :: from_iter ( iterator)
2178
+ SpecFromIterNested :: from_iter ( iterator)
2158
2179
}
2159
2180
}
2160
2181
@@ -2182,18 +2203,21 @@ impl<T> Drop for InPlaceDrop<T> {
2182
2203
}
2183
2204
}
2184
2205
2185
- impl < T > SpecFrom < T , IntoIter < T > > for Vec < T > {
2206
+ impl < T > SpecFromIter < T , IntoIter < T > > for Vec < T > {
2186
2207
fn from_iter ( iterator : IntoIter < T > ) -> Self {
2187
2208
// A common case is passing a vector into a function which immediately
2188
2209
// re-collects into a vector. We can short circuit this if the IntoIter
2189
2210
// 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 {
2194
2218
unsafe {
2195
2219
let it = ManuallyDrop :: new ( iterator) ;
2196
- if non_zero_offset {
2220
+ if has_advanced {
2197
2221
ptr:: copy ( it. ptr , it. buf . as_ptr ( ) , it. len ( ) ) ;
2198
2222
}
2199
2223
return Vec :: from_raw_parts ( it. buf . as_ptr ( ) , it. len ( ) , it. cap ) ;
@@ -2224,6 +2248,12 @@ fn write_in_place_with_drop<T>(
2224
2248
}
2225
2249
}
2226
2250
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.
2227
2257
#[ rustc_unsafe_specialization_marker]
2228
2258
trait SourceIterMarker : SourceIter < Source : AsIntoIter > { }
2229
2259
@@ -2235,7 +2265,7 @@ trait SourceIterMarker: SourceIter<Source: AsIntoIter> {}
2235
2265
// several other specializations already depend on.
2236
2266
impl < T > SourceIterMarker for T where T : SourceIter < Source : AsIntoIter > + InPlaceIterable { }
2237
2267
2238
- impl < T , I > SpecFrom < T , I > for Vec < T >
2268
+ impl < T , I > SpecFromIter < T , I > for Vec < T >
2239
2269
where
2240
2270
I : Iterator < Item = T > + SourceIterMarker ,
2241
2271
{
@@ -2251,7 +2281,8 @@ where
2251
2281
|| mem:: align_of :: < T > ( )
2252
2282
!= mem:: align_of :: < <<I as SourceIter >:: Source as AsIntoIter >:: Item > ( )
2253
2283
{
2254
- return SpecFromNested :: from_iter ( iterator) ;
2284
+ // fallback to more generic implementations
2285
+ return SpecFromIterNested :: from_iter ( iterator) ;
2255
2286
}
2256
2287
2257
2288
let ( src_buf, dst_buf, dst_end, cap) = unsafe {
@@ -2277,9 +2308,9 @@ where
2277
2308
debug_assert ! ( dst as * const _ <= src. ptr, "InPlaceIterable contract violation" ) ;
2278
2309
2279
2310
// drop any remaining values at the tail of the source
2280
- src. drop_in_place ( ) ;
2311
+ src. drop_remaining ( ) ;
2281
2312
// but prevent drop of the allocation itself once IntoIter goes out of scope
2282
- src. forget_in_place ( ) ;
2313
+ src. forget_allocation ( ) ;
2283
2314
2284
2315
let vec = unsafe {
2285
2316
let len = dst. offset_from ( dst_buf) as usize ;
@@ -2290,17 +2321,17 @@ where
2290
2321
}
2291
2322
}
2292
2323
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 >
2294
2325
where
2295
2326
I : Iterator < Item = & ' a T > ,
2296
2327
T : Clone ,
2297
2328
{
2298
2329
default fn from_iter ( iterator : I ) -> Self {
2299
- SpecFrom :: from_iter ( iterator. cloned ( ) )
2330
+ SpecFromIter :: from_iter ( iterator. cloned ( ) )
2300
2331
}
2301
2332
}
2302
2333
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 >
2304
2335
where
2305
2336
T : Copy ,
2306
2337
{
@@ -2824,7 +2855,7 @@ impl<T> IntoIter<T> {
2824
2855
ptr:: slice_from_raw_parts_mut ( self . ptr as * mut T , self . len ( ) )
2825
2856
}
2826
2857
2827
- fn drop_in_place ( & mut self ) {
2858
+ fn drop_remaining ( & mut self ) {
2828
2859
if mem:: needs_drop :: < T > ( ) {
2829
2860
unsafe {
2830
2861
ptr:: drop_in_place ( self . as_mut_slice ( ) ) ;
@@ -2835,7 +2866,7 @@ impl<T> IntoIter<T> {
2835
2866
2836
2867
/// Relinquishes the backing allocation, equivalent to
2837
2868
/// `ptr::write(&mut self, Vec::new().into_iter())`
2838
- fn forget_in_place ( & mut self ) {
2869
+ fn forget_allocation ( & mut self ) {
2839
2870
self . cap = 0 ;
2840
2871
self . buf = unsafe { NonNull :: new_unchecked ( RawVec :: NEW . ptr ( ) ) } ;
2841
2872
self . ptr = self . buf . as_ptr ( ) ;
0 commit comments