1919#![ cfg_attr( bootstrap, feature( min_const_generics) ) ]
2020#![ feature( min_specialization) ]
2121#![ cfg_attr( test, feature( test) ) ]
22+ #![ feature( rustc_attrs) ]
2223
2324use smallvec:: SmallVec ;
2425
2526use std:: alloc:: Layout ;
2627use std:: cell:: { Cell , RefCell } ;
2728use std:: cmp;
29+ use std:: iter:: Cloned ;
2830use std:: marker:: { PhantomData , Send } ;
2931use std:: mem:: { self , MaybeUninit } ;
3032use std:: ptr;
31- use std:: slice;
33+ use std:: slice:: { self , Iter } ;
3234
3335#[ inline( never) ]
3436#[ cold]
3537pub fn cold_path < F : FnOnce ( ) -> R , R > ( f : F ) -> R {
3638 f ( )
3739}
3840
41+ /// Move the contents of an iterator to a contiguous memory region.
42+ ///
43+ /// SAFETY: the caller must ensure that the destination memory is free and large enough to hold
44+ /// the contents of the iterator. Must not be called for iterators that may allocate on the same
45+ /// arena.
46+ #[ inline]
47+ unsafe fn write_from_iter < ' a , T , I : Iterator < Item = T > > (
48+ mut iter : I ,
49+ len : usize ,
50+ mem : * mut T ,
51+ ) -> & ' a mut [ T ] {
52+ let mut l = len;
53+ for i in 0 ..len {
54+ if let Some ( value) = iter. next ( ) {
55+ std:: ptr:: write ( mem. add ( i) , value) ;
56+ } else {
57+ l = i;
58+ break ;
59+ }
60+ }
61+ // We only return as many items as the iterator gave us, even
62+ // though it was supposed to give us `len`
63+ return std:: slice:: from_raw_parts_mut ( mem, l) ;
64+ }
65+
3966/// An arena that can hold objects of only one type.
4067pub struct TypedArena < T > {
4168 /// A pointer to the next object to be allocated.
@@ -133,6 +160,10 @@ where
133160 }
134161}
135162
163+ #[ rustc_unsafe_specialization_marker]
164+ trait Clonable : Clone { }
165+ impl < T : Clone > Clonable for T { }
166+
136167impl < T , const N : usize > IterExt < T > for std:: array:: IntoIter < T , N > {
137168 #[ inline]
138169 fn alloc_from_iter ( self , arena : & TypedArena < T > ) -> & mut [ T ] {
@@ -167,6 +198,25 @@ impl<T> IterExt<T> for Vec<T> {
167198 }
168199}
169200
201+ impl < ' a , T : ' a > IterExt < T > for Cloned < Iter < ' a , T > >
202+ where
203+ T : Clonable ,
204+ {
205+ #[ inline]
206+ fn alloc_from_iter ( self , arena : & TypedArena < T > ) -> & mut [ T ] {
207+ let len = self . len ( ) ;
208+ if len == 0 {
209+ return & mut [ ] ;
210+ }
211+ // Move the content to the arena by copying and then forgetting it
212+ unsafe {
213+ let len = self . len ( ) ;
214+ let start_ptr = arena. alloc_raw_slice ( len) ;
215+ write_from_iter ( self , len, start_ptr)
216+ }
217+ }
218+ }
219+
170220impl < A : smallvec:: Array > IterExt < A :: Item > for SmallVec < A > {
171221 #[ inline]
172222 fn alloc_from_iter ( mut self , arena : & TypedArena < A :: Item > ) -> & mut [ A :: Item ] {
@@ -489,28 +539,6 @@ impl DroplessArena {
489539 }
490540 }
491541
492- #[ inline]
493- unsafe fn write_from_iter < T , I : Iterator < Item = T > > (
494- & self ,
495- mut iter : I ,
496- len : usize ,
497- mem : * mut T ,
498- ) -> & mut [ T ] {
499- let mut i = 0 ;
500- // Use a manual loop since LLVM manages to optimize it better for
501- // slice iterators
502- loop {
503- let value = iter. next ( ) ;
504- if i >= len || value. is_none ( ) {
505- // We only return as many items as the iterator gave us, even
506- // though it was supposed to give us `len`
507- return slice:: from_raw_parts_mut ( mem, i) ;
508- }
509- ptr:: write ( mem. add ( i) , value. unwrap ( ) ) ;
510- i += 1 ;
511- }
512- }
513-
514542 #[ inline]
515543 pub fn alloc_from_iter < T , I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
516544 let iter = iter. into_iter ( ) ;
@@ -529,7 +557,7 @@ impl DroplessArena {
529557 }
530558
531559 let mem = self . alloc_raw ( Layout :: array :: < T > ( len) . unwrap ( ) ) as * mut T ;
532- unsafe { self . write_from_iter ( iter, len, mem) }
560+ unsafe { write_from_iter ( iter, len, mem) }
533561 }
534562 ( _, _) => {
535563 cold_path ( move || -> & mut [ T ] {
0 commit comments