@@ -114,20 +114,44 @@ pub(crate) mod hack {
114
114
#[ cfg( not( no_global_oom_handling) ) ]
115
115
#[ inline]
116
116
#[ allow( unused_braces) ]
117
- pub fn to_vec < T : ConvertVec , A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
117
+ pub fn to_vec < T : ConvertVec , A : Allocator > (
118
+ s : & [ T ] ,
119
+ alloc : A ,
120
+ ) -> Vec < T , A >
121
+ where
122
+ [ ( ) ; { crate :: meta_num_slots_default!( A ) } ] : ,
123
+ {
124
+ T :: to_vec ( s, alloc)
125
+ }
126
+
127
+ #[ cfg( not( no_global_oom_handling) ) ]
128
+ #[ inline]
129
+ #[ allow( unused_braces) ]
130
+ pub fn to_vec_co < T : ConvertVecCo , A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
118
131
s : & [ T ] ,
119
132
alloc : A ,
120
133
) -> Vec < T , A , CO_ALLOC_PREF >
121
134
where
122
135
[ ( ) ; { crate :: meta_num_slots!( A , CO_ALLOC_PREF ) } ] : ,
123
136
{
124
- T :: to_vec ( s, alloc)
137
+ T :: to_vec_co ( s, alloc)
125
138
}
126
139
127
140
#[ cfg( not( no_global_oom_handling) ) ]
128
141
#[ allow( unused_braces) ]
129
142
pub trait ConvertVec {
130
- fn to_vec < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
143
+ fn to_vec < A : Allocator > (
144
+ s : & [ Self ] ,
145
+ alloc : A ,
146
+ ) -> Vec < Self , A >
147
+ where
148
+ Self : Sized ,
149
+ [ ( ) ; { crate :: meta_num_slots_default!( A ) } ] : ;
150
+ }
151
+
152
+ #[ allow( unused_braces) ]
153
+ pub trait ConvertVecCo {
154
+ fn to_vec_co < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
131
155
s : & [ Self ] ,
132
156
alloc : A ,
133
157
) -> Vec < Self , A , CO_ALLOC_PREF >
@@ -141,7 +165,82 @@ pub(crate) mod hack {
141
165
impl < T : Clone > ConvertVec for T {
142
166
#[ inline]
143
167
#[ allow( unused_braces) ]
144
- default fn to_vec < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
168
+ default fn to_vec < A : Allocator > (
169
+ s : & [ Self ] ,
170
+ alloc : A ,
171
+ ) -> Vec < Self , A >
172
+ where
173
+ [ ( ) ; { crate :: meta_num_slots_default!( A ) } ] : ,
174
+ {
175
+ #[ allow( unused_braces) ]
176
+ struct DropGuard < ' a , T , A : Allocator >
177
+ where
178
+ [ ( ) ; { crate :: meta_num_slots_default!( A ) } ] : ,
179
+ {
180
+ vec : & ' a mut Vec < T , A > ,
181
+ num_init : usize ,
182
+ }
183
+ impl < ' a , T , A : Allocator > Drop for DropGuard < ' a , T , A >
184
+ where
185
+ [ ( ) ; { crate :: meta_num_slots_default!( A ) } ] : ,
186
+ {
187
+ #[ inline]
188
+ fn drop ( & mut self ) {
189
+ // SAFETY:
190
+ // items were marked initialized in the loop below
191
+ unsafe {
192
+ self . vec . set_len ( self . num_init ) ;
193
+ }
194
+ }
195
+ }
196
+ let mut vec = Vec :: with_capacity_in ( s. len ( ) , alloc) ;
197
+ let mut guard = DropGuard { vec : & mut vec, num_init : 0 } ;
198
+ let slots = guard. vec . spare_capacity_mut ( ) ;
199
+ // .take(slots.len()) is necessary for LLVM to remove bounds checks
200
+ // and has better codegen than zip.
201
+ for ( i, b) in s. iter ( ) . enumerate ( ) . take ( slots. len ( ) ) {
202
+ guard. num_init = i;
203
+ slots[ i] . write ( b. clone ( ) ) ;
204
+ }
205
+ core:: mem:: forget ( guard) ;
206
+ // SAFETY:
207
+ // the vec was allocated and initialized above to at least this length.
208
+ unsafe {
209
+ vec. set_len ( s. len ( ) ) ;
210
+ }
211
+ vec
212
+ }
213
+ }
214
+
215
+ #[ cfg( not( no_global_oom_handling) ) ]
216
+ impl < T : Copy > ConvertVec for T {
217
+ #[ inline]
218
+ #[ allow( unused_braces) ]
219
+ fn to_vec < A : Allocator > (
220
+ s : & [ Self ] ,
221
+ alloc : A ,
222
+ ) -> Vec < Self , A >
223
+ where
224
+ [ ( ) ; { crate :: meta_num_slots_default!( A ) } ] : ,
225
+ {
226
+ let mut v = Vec :: with_capacity_in ( s. len ( ) , alloc) ;
227
+ // SAFETY:
228
+ // allocated above with the capacity of `s`, and initialize to `s.len()` in
229
+ // ptr::copy_to_non_overlapping below.
230
+ unsafe {
231
+ s. as_ptr ( ) . copy_to_nonoverlapping ( v. as_mut_ptr ( ) , s. len ( ) ) ;
232
+ v. set_len ( s. len ( ) ) ;
233
+ }
234
+ v
235
+ }
236
+ }
237
+
238
+ #[ cfg( not( no_global_oom_handling) ) ]
239
+ #[ allow( unused_braces) ]
240
+ impl < T : Clone > ConvertVecCo for T {
241
+ #[ inline]
242
+ #[ allow( unused_braces) ]
243
+ default fn to_vec_co < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
145
244
s : & [ Self ] ,
146
245
alloc : A ,
147
246
) -> Vec < Self , A , CO_ALLOC_PREF >
@@ -189,10 +288,10 @@ pub(crate) mod hack {
189
288
}
190
289
191
290
#[ cfg( not( no_global_oom_handling) ) ]
192
- impl < T : Copy > ConvertVec for T {
291
+ impl < T : Copy > ConvertVecCo for T {
193
292
#[ inline]
194
293
#[ allow( unused_braces) ]
195
- fn to_vec < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
294
+ fn to_vec_co < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > (
196
295
s : & [ Self ] ,
197
296
alloc : A ,
198
297
) -> Vec < Self , A , CO_ALLOC_PREF >
@@ -209,8 +308,7 @@ pub(crate) mod hack {
209
308
}
210
309
v
211
310
}
212
- }
213
- }
311
+ } }
214
312
215
313
#[ cfg( not( test) ) ]
216
314
impl < T > [ T ] {
@@ -455,7 +553,7 @@ impl<T> [T] {
455
553
T : Clone ,
456
554
[ ( ) ; { meta_num_slots_global ! ( CO_ALLOC_PREF ) } ] : ,
457
555
{
458
- self . to_vec_in :: < Global , CO_ALLOC_PREF > ( Global )
556
+ self . to_vec_in_co :: < Global , CO_ALLOC_PREF > ( Global )
459
557
}
460
558
461
559
/// Copies `self` into a new `Vec` with an allocator.
@@ -476,15 +574,30 @@ impl<T> [T] {
476
574
#[ inline]
477
575
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
478
576
#[ allow( unused_braces) ]
479
- pub fn to_vec_in < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > ( & self , alloc : A ) -> Vec < T , A , CO_ALLOC_PREF >
577
+ pub fn to_vec_in < A : Allocator > ( & self , alloc : A ) -> Vec < T , A >
480
578
where
481
579
T : Clone ,
482
- [ ( ) ; { crate :: meta_num_slots !( A , CO_ALLOC_PREF ) } ] : ,
580
+ [ ( ) ; { crate :: meta_num_slots_default !( A ) } ] : ,
483
581
{
484
582
// N.B., see the `hack` module in this file for more details.
485
583
hack:: to_vec ( self , alloc)
486
584
}
487
585
586
+ /// Coallocation-aware version of `to_vec_in`.
587
+ #[ cfg( not( no_global_oom_handling) ) ]
588
+ #[ rustc_allow_incoherent_impl]
589
+ #[ inline]
590
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
591
+ #[ allow( unused_braces) ]
592
+ pub fn to_vec_in_co < A : Allocator , const CO_ALLOC_PREF : CoAllocPref > ( & self , alloc : A ) -> Vec < T , A , CO_ALLOC_PREF >
593
+ where
594
+ T : Clone ,
595
+ [ ( ) ; { crate :: meta_num_slots!( A , CO_ALLOC_PREF ) } ] : ,
596
+ {
597
+ // N.B., see the `hack` module in this file for more details.
598
+ hack:: to_vec_co ( self , alloc)
599
+ }
600
+
488
601
/// Converts `self` into a vector without clones or allocation.
489
602
///
490
603
/// The resulting vector can be converted back into a box via
0 commit comments