@@ -191,6 +191,8 @@ impl<T> TypedArena<T> {
191191 #[ inline]
192192 pub fn alloc_from_iter < I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
193193 assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
194+ // To handle the possibility that the act of iterating itself causes allocations on
195+ // the arena, we must collect into a local buffer first, then copy it into the arena.
194196 let mut vec: SmallVec < [ _ ; 8 ] > = iter. into_iter ( ) . collect ( ) ;
195197 if vec. is_empty ( ) {
196198 return & mut [ ] ;
@@ -431,66 +433,26 @@ impl DroplessArena {
431433 }
432434 }
433435
434- #[ inline]
435- unsafe fn write_from_iter < T , I : Iterator < Item = T > > (
436- & self ,
437- mut iter : I ,
438- len : usize ,
439- mem : * mut T ,
440- ) -> & mut [ T ] {
441- let mut i = 0 ;
442- // Use a manual loop since LLVM manages to optimize it better for
443- // slice iterators
444- loop {
445- let value = iter. next ( ) ;
446- if i >= len || value. is_none ( ) {
447- // We only return as many items as the iterator gave us, even
448- // though it was supposed to give us `len`
449- return slice:: from_raw_parts_mut ( mem, i) ;
450- }
451- ptr:: write ( mem. add ( i) , value. unwrap ( ) ) ;
452- i += 1 ;
453- }
454- }
455-
456436 #[ inline]
457437 pub fn alloc_from_iter < T , I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
458438 let iter = iter. into_iter ( ) ;
459439 assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
460440 assert ! ( !mem:: needs_drop:: <T >( ) ) ;
461441
462- let size_hint = iter. size_hint ( ) ;
463-
464- match size_hint {
465- ( min, Some ( max) ) if min == max => {
466- // We know the exact number of elements the iterator will produce here
467- let len = min;
468-
469- if len == 0 {
470- return & mut [ ] ;
471- }
472-
473- let mem = self . alloc_raw ( Layout :: array :: < T > ( len) . unwrap ( ) ) as * mut T ;
474- unsafe { self . write_from_iter ( iter, len, mem) }
475- }
476- ( _, _) => {
477- cold_path ( move || -> & mut [ T ] {
478- let mut vec: SmallVec < [ _ ; 8 ] > = iter. collect ( ) ;
479- if vec. is_empty ( ) {
480- return & mut [ ] ;
481- }
482- // Move the content to the arena by copying it and then forgetting
483- // the content of the SmallVec
484- unsafe {
485- let len = vec. len ( ) ;
486- let start_ptr =
487- self . alloc_raw ( Layout :: for_value :: < [ T ] > ( vec. as_slice ( ) ) ) as * mut T ;
488- vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
489- vec. set_len ( 0 ) ;
490- slice:: from_raw_parts_mut ( start_ptr, len)
491- }
492- } )
493- }
442+ // To handle the possibility that the act of iterating itself causes allocations on
443+ // the arena, we must collect into a local buffer first, then copy it into the arena.
444+ let mut vec: SmallVec < [ _ ; 8 ] > = iter. collect ( ) ;
445+ if vec. is_empty ( ) {
446+ return & mut [ ] ;
447+ }
448+ // Move the content to the arena by copying it and then forgetting
449+ // the content of the SmallVec
450+ unsafe {
451+ let len = vec. len ( ) ;
452+ let start_ptr = self . alloc_raw ( Layout :: for_value :: < [ T ] > ( vec. as_slice ( ) ) ) as * mut T ;
453+ vec. as_ptr ( ) . copy_to_nonoverlapping ( start_ptr, len) ;
454+ vec. set_len ( 0 ) ;
455+ slice:: from_raw_parts_mut ( start_ptr, len)
494456 }
495457 }
496458}
@@ -542,6 +504,8 @@ impl DropArena {
542504
543505 #[ inline]
544506 pub unsafe fn alloc_from_iter < T , I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
507+ // To handle the possibility that the act of iterating itself causes allocations on
508+ // the arena, we must collect into a local buffer first, then copy it into the arena.
545509 let mut vec: SmallVec < [ _ ; 8 ] > = iter. into_iter ( ) . collect ( ) ;
546510 if vec. is_empty ( ) {
547511 return & mut [ ] ;
0 commit comments