@@ -93,11 +93,11 @@ use core::mem::size_of;
9393use core:: ptr;
9494
9595use crate :: alloc:: Allocator ;
96- #[ cfg( not( no_global_oom_handling) ) ]
9796use crate :: alloc:: Global ;
9897#[ cfg( not( no_global_oom_handling) ) ]
9998use crate :: borrow:: ToOwned ;
10099use crate :: boxed:: Box ;
100+ use crate :: collections:: TryReserveError ;
101101use crate :: vec:: Vec ;
102102
103103#[ unstable( feature = "slice_range" , issue = "76393" ) ]
@@ -153,6 +153,7 @@ mod hack {
153153 use core:: alloc:: Allocator ;
154154
155155 use crate :: boxed:: Box ;
156+ use crate :: collections:: TryReserveError ;
156157 use crate :: vec:: Vec ;
157158
158159 // We shouldn't add inline attribute to this since this is used in
@@ -172,13 +173,27 @@ mod hack {
172173 T :: to_vec ( s, alloc)
173174 }
174175
176+ #[ inline]
177+ pub fn try_to_vec < T : TryConvertVec , A : Allocator > (
178+ s : & [ T ] ,
179+ alloc : A ,
180+ ) -> Result < Vec < T , A > , TryReserveError > {
181+ T :: try_to_vec ( s, alloc)
182+ }
183+
175184 #[ cfg( not( no_global_oom_handling) ) ]
176185 pub trait ConvertVec {
177186 fn to_vec < A : Allocator > ( s : & [ Self ] , alloc : A ) -> Vec < Self , A >
178187 where
179188 Self : Sized ;
180189 }
181190
191+ pub trait TryConvertVec {
192+ fn try_to_vec < A : Allocator > ( s : & [ Self ] , alloc : A ) -> Result < Vec < Self , A > , TryReserveError >
193+ where
194+ Self : Sized ;
195+ }
196+
182197 #[ cfg( not( no_global_oom_handling) ) ]
183198 impl < T : Clone > ConvertVec for T {
184199 #[ inline]
@@ -231,6 +246,45 @@ mod hack {
231246 v
232247 }
233248 }
249+
250+ impl < T : Clone > TryConvertVec for T {
251+ #[ inline]
252+ default fn try_to_vec < A : Allocator > (
253+ s : & [ Self ] ,
254+ alloc : A ,
255+ ) -> Result < Vec < Self , A > , TryReserveError > {
256+ struct DropGuard < ' a , T , A : Allocator > {
257+ vec : & ' a mut Vec < T , A > ,
258+ num_init : usize ,
259+ }
260+ impl < ' a , T , A : Allocator > Drop for DropGuard < ' a , T , A > {
261+ #[ inline]
262+ fn drop ( & mut self ) {
263+ // SAFETY:
264+ // items were marked initialized in the loop below
265+ unsafe {
266+ self . vec . set_len ( self . num_init ) ;
267+ }
268+ }
269+ }
270+ let mut vec = Vec :: try_with_capacity_in ( s. len ( ) , alloc) ?;
271+ let mut guard = DropGuard { vec : & mut vec, num_init : 0 } ;
272+ let slots = guard. vec . spare_capacity_mut ( ) ;
273+ // .take(slots.len()) is necessary for LLVM to remove bounds checks
274+ // and has better codegen than zip.
275+ for ( i, b) in s. iter ( ) . enumerate ( ) . take ( slots. len ( ) ) {
276+ guard. num_init = i;
277+ slots[ i] . write ( b. clone ( ) ) ;
278+ }
279+ core:: mem:: forget ( guard) ;
280+ // SAFETY:
281+ // the vec was allocated and initialized above to at least this length.
282+ unsafe {
283+ vec. set_len ( s. len ( ) ) ;
284+ }
285+ Ok ( vec)
286+ }
287+ }
234288}
235289
236290#[ lang = "slice_alloc" ]
@@ -470,6 +524,24 @@ impl<T> [T] {
470524 self . to_vec_in ( Global )
471525 }
472526
527+ /// Tries to copy `self` into a new `Vec`.
528+ ///
529+ /// # Examples
530+ ///
531+ /// ```
532+ /// let s = [10, 40, 30];
533+ /// let x = s.try_to_vec().unwrap();
534+ /// // Here, `s` and `x` can be modified independently.
535+ /// ```
536+ #[ inline]
537+ #[ unstable( feature = "more_fallible_allocation_methods" , issue = "86942" ) ]
538+ pub fn try_to_vec ( & self ) -> Result < Vec < T > , TryReserveError >
539+ where
540+ T : Clone ,
541+ {
542+ self . try_to_vec_in ( Global )
543+ }
544+
473545 /// Copies `self` into a new `Vec` with an allocator.
474546 ///
475547 /// # Examples
@@ -494,6 +566,29 @@ impl<T> [T] {
494566 hack:: to_vec ( self , alloc)
495567 }
496568
569+ /// Tries to copy `self` into a new `Vec` with an allocator.
570+ ///
571+ /// # Examples
572+ ///
573+ /// ```
574+ /// #![feature(allocator_api)]
575+ ///
576+ /// use std::alloc::System;
577+ ///
578+ /// let s = [10, 40, 30];
579+ /// let x = s.try_to_vec_in(System).unwrap();
580+ /// // Here, `s` and `x` can be modified independently.
581+ /// ```
582+ #[ inline]
583+ #[ unstable( feature = "more_fallible_allocation_methods" , issue = "86942" ) ]
584+ pub fn try_to_vec_in < A : Allocator > ( & self , alloc : A ) -> Result < Vec < T , A > , TryReserveError >
585+ where
586+ T : Clone ,
587+ {
588+ // N.B., see the `hack` module in this file for more details.
589+ hack:: try_to_vec ( self , alloc)
590+ }
591+
497592 /// Converts `self` into a vector without clones or allocation.
498593 ///
499594 /// The resulting vector can be converted back into a box via
0 commit comments