@@ -93,11 +93,11 @@ use core::mem::size_of;
93
93
use core:: ptr;
94
94
95
95
use crate :: alloc:: Allocator ;
96
- #[ cfg( not( no_global_oom_handling) ) ]
97
96
use crate :: alloc:: Global ;
98
97
#[ cfg( not( no_global_oom_handling) ) ]
99
98
use crate :: borrow:: ToOwned ;
100
99
use crate :: boxed:: Box ;
100
+ use crate :: collections:: TryReserveError ;
101
101
use crate :: vec:: Vec ;
102
102
103
103
#[ unstable( feature = "slice_range" , issue = "76393" ) ]
@@ -153,6 +153,7 @@ mod hack {
153
153
use core:: alloc:: Allocator ;
154
154
155
155
use crate :: boxed:: Box ;
156
+ use crate :: collections:: TryReserveError ;
156
157
use crate :: vec:: Vec ;
157
158
158
159
// We shouldn't add inline attribute to this since this is used in
@@ -172,13 +173,27 @@ mod hack {
172
173
T :: to_vec ( s, alloc)
173
174
}
174
175
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
+
175
184
#[ cfg( not( no_global_oom_handling) ) ]
176
185
pub trait ConvertVec {
177
186
fn to_vec < A : Allocator > ( s : & [ Self ] , alloc : A ) -> Vec < Self , A >
178
187
where
179
188
Self : Sized ;
180
189
}
181
190
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
+
182
197
#[ cfg( not( no_global_oom_handling) ) ]
183
198
impl < T : Clone > ConvertVec for T {
184
199
#[ inline]
@@ -231,6 +246,45 @@ mod hack {
231
246
v
232
247
}
233
248
}
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
+ }
234
288
}
235
289
236
290
#[ lang = "slice_alloc" ]
@@ -470,6 +524,24 @@ impl<T> [T] {
470
524
self . to_vec_in ( Global )
471
525
}
472
526
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
+
473
545
/// Copies `self` into a new `Vec` with an allocator.
474
546
///
475
547
/// # Examples
@@ -494,6 +566,29 @@ impl<T> [T] {
494
566
hack:: to_vec ( self , alloc)
495
567
}
496
568
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
+
497
592
/// Converts `self` into a vector without clones or allocation.
498
593
///
499
594
/// The resulting vector can be converted back into a box via
0 commit comments