1414#![ feature( dropck_eyepatch) ]
1515#![ feature( new_uninit) ]
1616#![ feature( maybe_uninit_slice) ]
17+ #![ feature( min_specialization) ]
18+ #![ feature( trusted_len) ]
1719#![ cfg_attr( test, feature( test) ) ]
1820
1921use rustc_data_structures:: cold_path;
@@ -22,6 +24,7 @@ use smallvec::SmallVec;
2224use std:: alloc:: Layout ;
2325use std:: cell:: { Cell , RefCell } ;
2426use std:: cmp;
27+ use std:: iter:: TrustedLen ;
2528use std:: marker:: { PhantomData , Send } ;
2629use std:: mem:: { self , MaybeUninit } ;
2730use std:: ptr;
@@ -109,6 +112,53 @@ impl<T> Default for TypedArena<T> {
109112 }
110113}
111114
115+ trait IterExt < I , T > {
116+ fn write_to_arena ( iter : I , arena : & TypedArena < T > ) -> & mut [ T ] ;
117+ }
118+
119+ impl < T , I > IterExt < I , T > for I
120+ where
121+ I : Iterator < Item = T > ,
122+ {
123+ #[ inline]
124+ default fn write_to_arena ( iter : I , arena : & TypedArena < T > ) -> & mut [ T ] {
125+ arena. alloc_from_iter_gen ( iter)
126+ }
127+ }
128+
129+ impl < T , I > IterExt < I , T > for I
130+ where
131+ I : Iterator < Item = T > + TrustedLen ,
132+ {
133+ #[ inline]
134+ fn write_to_arena ( mut iter : I , arena : & TypedArena < T > ) -> & mut [ T ] {
135+ let size_hint = iter. size_hint ( ) ;
136+
137+ match size_hint {
138+ ( 0 , Some ( _) ) => & mut [ ] ,
139+ ( len, Some ( _) ) => {
140+ // no need to check min == max because of TrustedLen
141+
142+ // SAFETY: TrustedLen implementors must ensure they return exactly as many
143+ // elements as they tell via `size_hint()`.
144+ unsafe {
145+ // We know the exact number of elements the iterator will produce here
146+ let start_addr = arena. alloc_raw_slice ( len) ;
147+ let mut mem = start_addr;
148+
149+ while let Some ( value) = iter. next ( ) {
150+ ptr:: write ( mem, value) ;
151+ mem = mem. add ( 1 ) ;
152+ }
153+
154+ return slice:: from_raw_parts_mut ( start_addr, len) ;
155+ }
156+ }
157+ _ => panic ! ( "Trying to allocate from an iterator with more than usize::MAX elements" ) ,
158+ }
159+ }
160+ }
161+
112162impl < T > TypedArena < T > {
113163 /// Allocates an object in the `TypedArena`, returning a reference to it.
114164 #[ inline]
@@ -183,10 +233,10 @@ impl<T> TypedArena<T> {
183233 }
184234 }
185235
236+ /// General case implementation for `alloc_from_iter()`.
186237 #[ inline]
187- pub fn alloc_from_iter < I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
188- assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
189- let mut vec: SmallVec < [ _ ; 8 ] > = iter. into_iter ( ) . collect ( ) ;
238+ fn alloc_from_iter_gen < I : Iterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
239+ let mut vec: SmallVec < [ _ ; 8 ] > = iter. collect ( ) ;
190240 if vec. is_empty ( ) {
191241 return & mut [ ] ;
192242 }
@@ -201,6 +251,14 @@ impl<T> TypedArena<T> {
201251 }
202252 }
203253
254+ #[ inline]
255+ pub fn alloc_from_iter < I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
256+ let iter = iter. into_iter ( ) ;
257+ assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
258+
259+ I :: IntoIter :: write_to_arena ( iter, self )
260+ }
261+
204262 /// Grows the arena.
205263 #[ inline( never) ]
206264 #[ cold]
0 commit comments