@@ -114,20 +114,44 @@ pub(crate) mod hack {
114114 #[ cfg( not( no_global_oom_handling) ) ]
115115 #[ inline]
116116 #[ 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 > (
118131 s : & [ T ] ,
119132 alloc : A ,
120133 ) -> Vec < T , A , CO_ALLOC_PREF >
121134 where
122135 [ ( ) ; { crate :: meta_num_slots!( A , CO_ALLOC_PREF ) } ] : ,
123136 {
124- T :: to_vec ( s, alloc)
137+ T :: to_vec_co ( s, alloc)
125138 }
126139
127140 #[ cfg( not( no_global_oom_handling) ) ]
128141 #[ allow( unused_braces) ]
129142 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 > (
131155 s : & [ Self ] ,
132156 alloc : A ,
133157 ) -> Vec < Self , A , CO_ALLOC_PREF >
@@ -141,7 +165,82 @@ pub(crate) mod hack {
141165 impl < T : Clone > ConvertVec for T {
142166 #[ inline]
143167 #[ 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 > (
145244 s : & [ Self ] ,
146245 alloc : A ,
147246 ) -> Vec < Self , A , CO_ALLOC_PREF >
@@ -189,10 +288,10 @@ pub(crate) mod hack {
189288 }
190289
191290 #[ cfg( not( no_global_oom_handling) ) ]
192- impl < T : Copy > ConvertVec for T {
291+ impl < T : Copy > ConvertVecCo for T {
193292 #[ inline]
194293 #[ 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 > (
196295 s : & [ Self ] ,
197296 alloc : A ,
198297 ) -> Vec < Self , A , CO_ALLOC_PREF >
@@ -209,8 +308,7 @@ pub(crate) mod hack {
209308 }
210309 v
211310 }
212- }
213- }
311+ } }
214312
215313#[ cfg( not( test) ) ]
216314impl < T > [ T ] {
@@ -455,7 +553,7 @@ impl<T> [T] {
455553 T : Clone ,
456554 [ ( ) ; { meta_num_slots_global ! ( CO_ALLOC_PREF ) } ] : ,
457555 {
458- self . to_vec_in :: < Global , CO_ALLOC_PREF > ( Global )
556+ self . to_vec_in_co :: < Global , CO_ALLOC_PREF > ( Global )
459557 }
460558
461559 /// Copies `self` into a new `Vec` with an allocator.
@@ -476,15 +574,30 @@ impl<T> [T] {
476574 #[ inline]
477575 #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
478576 #[ 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 >
480578 where
481579 T : Clone ,
482- [ ( ) ; { crate :: meta_num_slots !( A , CO_ALLOC_PREF ) } ] : ,
580+ [ ( ) ; { crate :: meta_num_slots_default !( A ) } ] : ,
483581 {
484582 // N.B., see the `hack` module in this file for more details.
485583 hack:: to_vec ( self , alloc)
486584 }
487585
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+
488601 /// Converts `self` into a vector without clones or allocation.
489602 ///
490603 /// The resulting vector can be converted back into a box via
0 commit comments