@@ -191,6 +191,8 @@ impl<T> TypedArena<T> {
191
191
#[ inline]
192
192
pub fn alloc_from_iter < I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
193
193
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.
194
196
let mut vec: SmallVec < [ _ ; 8 ] > = iter. into_iter ( ) . collect ( ) ;
195
197
if vec. is_empty ( ) {
196
198
return & mut [ ] ;
@@ -431,66 +433,26 @@ impl DroplessArena {
431
433
}
432
434
}
433
435
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
-
456
436
#[ inline]
457
437
pub fn alloc_from_iter < T , I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
458
438
let iter = iter. into_iter ( ) ;
459
439
assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
460
440
assert ! ( !mem:: needs_drop:: <T >( ) ) ;
461
441
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)
494
456
}
495
457
}
496
458
}
@@ -542,6 +504,8 @@ impl DropArena {
542
504
543
505
#[ inline]
544
506
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.
545
509
let mut vec: SmallVec < [ _ ; 8 ] > = iter. into_iter ( ) . collect ( ) ;
546
510
if vec. is_empty ( ) {
547
511
return & mut [ ] ;
0 commit comments