2121#![ feature( decl_macro) ]
2222#![ feature( dropck_eyepatch) ]
2323#![ feature( maybe_uninit_slice) ]
24+ #![ feature( never_type) ]
2425#![ feature( rustc_attrs) ]
2526#![ feature( rustdoc_internals) ]
27+ #![ feature( unwrap_infallible) ]
2628// tidy-alphabetical-end
2729
2830use std:: alloc:: Layout ;
@@ -200,6 +202,18 @@ impl<T> TypedArena<T> {
200202 /// storing the elements in the arena.
201203 #[ inline]
202204 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 > {
203217 // Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason
204218 // is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a
205219 // reference to `self` and adding elements to the arena during iteration.
@@ -214,18 +228,19 @@ impl<T> TypedArena<T> {
214228 // doesn't need to be hyper-optimized.
215229 assert ! ( size_of:: <T >( ) != 0 ) ;
216230
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?;
218233 if vec. is_empty ( ) {
219- return & mut [ ] ;
234+ return Ok ( & mut [ ] ) ;
220235 }
221236 // Move the content to the arena by copying and then forgetting it.
222237 let len = vec. len ( ) ;
223238 let start_ptr = self . alloc_raw_slice ( len) ;
224- unsafe {
239+ Ok ( unsafe {
225240 vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
226241 vec. set_len ( 0 ) ;
227242 slice:: from_raw_parts_mut ( start_ptr, len)
228- }
243+ } )
229244 }
230245
231246 /// Grows the arena.
@@ -566,27 +581,34 @@ impl DroplessArena {
566581 // `drop`.
567582 unsafe { self . write_from_iter ( iter, len, mem) }
568583 }
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 ( ) ) ,
588585 }
589586 }
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+ }
590612}
591613
592614/// Declare an `Arena` containing one dropless arena and many typed arenas (the
0 commit comments