21
21
#![ feature( decl_macro) ]
22
22
#![ feature( dropck_eyepatch) ]
23
23
#![ feature( maybe_uninit_slice) ]
24
+ #![ feature( never_type) ]
24
25
#![ feature( rustc_attrs) ]
25
26
#![ feature( rustdoc_internals) ]
27
+ #![ feature( unwrap_infallible) ]
26
28
// tidy-alphabetical-end
27
29
28
30
use std:: alloc:: Layout ;
@@ -200,6 +202,18 @@ impl<T> TypedArena<T> {
200
202
/// storing the elements in the arena.
201
203
#[ inline]
202
204
pub fn alloc_from_iter < I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
205
+ self . try_alloc_from_iter ( iter. into_iter ( ) . map ( Ok :: < T , !> ) ) . into_ok ( )
206
+ }
207
+
208
+ /// Allocates the elements of this iterator into a contiguous slice in the `TypedArena`.
209
+ ///
210
+ /// Note: for reasons of reentrancy and panic safety we collect into a `SmallVec<[_; 8]>` before
211
+ /// storing the elements in the arena.
212
+ #[ inline]
213
+ pub fn try_alloc_from_iter < E > (
214
+ & self ,
215
+ iter : impl IntoIterator < Item = Result < T , E > > ,
216
+ ) -> Result < & mut [ T ] , E > {
203
217
// Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason
204
218
// is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a
205
219
// reference to `self` and adding elements to the arena during iteration.
@@ -214,18 +228,19 @@ impl<T> TypedArena<T> {
214
228
// doesn't need to be hyper-optimized.
215
229
assert ! ( size_of:: <T >( ) != 0 ) ;
216
230
217
- let mut vec: SmallVec < [ _ ; 8 ] > = iter. into_iter ( ) . collect ( ) ;
231
+ let vec: Result < SmallVec < [ T ; 8 ] > , E > = iter. into_iter ( ) . collect ( ) ;
232
+ let mut vec = vec?;
218
233
if vec. is_empty ( ) {
219
- return & mut [ ] ;
234
+ return Ok ( & mut [ ] ) ;
220
235
}
221
236
// Move the content to the arena by copying and then forgetting it.
222
237
let len = vec. len ( ) ;
223
238
let start_ptr = self . alloc_raw_slice ( len) ;
224
- unsafe {
239
+ Ok ( unsafe {
225
240
vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
226
241
vec. set_len ( 0 ) ;
227
242
slice:: from_raw_parts_mut ( start_ptr, len)
228
- }
243
+ } )
229
244
}
230
245
231
246
/// Grows the arena.
@@ -566,27 +581,34 @@ impl DroplessArena {
566
581
// `drop`.
567
582
unsafe { self . write_from_iter ( iter, len, mem) }
568
583
}
569
- ( _, _) => {
570
- outline ( move || -> & mut [ T ] {
571
- // Takes care of reentrancy.
572
- let mut vec: SmallVec < [ _ ; 8 ] > = iter. collect ( ) ;
573
- if vec. is_empty ( ) {
574
- return & mut [ ] ;
575
- }
576
- // Move the content to the arena by copying it and then forgetting
577
- // the content of the SmallVec
578
- unsafe {
579
- let len = vec. len ( ) ;
580
- let start_ptr =
581
- self . alloc_raw ( Layout :: for_value :: < [ T ] > ( vec. as_slice ( ) ) ) as * mut T ;
582
- vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
583
- vec. set_len ( 0 ) ;
584
- slice:: from_raw_parts_mut ( start_ptr, len)
585
- }
586
- } )
587
- }
584
+ ( _, _) => outline ( move || self . try_alloc_from_iter ( iter. map ( Ok :: < T , !> ) ) . into_ok ( ) ) ,
588
585
}
589
586
}
587
+
588
+ #[ inline]
589
+ pub fn try_alloc_from_iter < T , E > (
590
+ & self ,
591
+ iter : impl IntoIterator < Item = Result < T , E > > ,
592
+ ) -> Result < & mut [ T ] , E > {
593
+ // Despite the similarlty with `alloc_from_iter`, we cannot reuse their fast case, as we
594
+ // cannot know the minimum length of the iterator in this case.
595
+ assert ! ( size_of:: <T >( ) != 0 ) ;
596
+
597
+ // Takes care of reentrancy.
598
+ let vec: Result < SmallVec < [ T ; 8 ] > , E > = iter. into_iter ( ) . collect ( ) ;
599
+ let mut vec = vec?;
600
+ if vec. is_empty ( ) {
601
+ return Ok ( & mut [ ] ) ;
602
+ }
603
+ // Move the content to the arena by copying and then forgetting it.
604
+ let len = vec. len ( ) ;
605
+ Ok ( unsafe {
606
+ let start_ptr = self . alloc_raw ( Layout :: for_value :: < [ T ] > ( vec. as_slice ( ) ) ) as * mut T ;
607
+ vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
608
+ vec. set_len ( 0 ) ;
609
+ slice:: from_raw_parts_mut ( start_ptr, len)
610
+ } )
611
+ }
590
612
}
591
613
592
614
/// Declare an `Arena` containing one dropless arena and many typed arenas (the
0 commit comments