14
14
#![ feature( dropck_eyepatch) ]
15
15
#![ feature( new_uninit) ]
16
16
#![ feature( maybe_uninit_slice) ]
17
+ #![ feature( min_specialization) ]
18
+ #![ feature( trusted_len) ]
17
19
#![ cfg_attr( test, feature( test) ) ]
18
20
19
21
use rustc_data_structures:: cold_path;
@@ -22,6 +24,7 @@ use smallvec::SmallVec;
22
24
use std:: alloc:: Layout ;
23
25
use std:: cell:: { Cell , RefCell } ;
24
26
use std:: cmp;
27
+ use std:: iter:: TrustedLen ;
25
28
use std:: marker:: { PhantomData , Send } ;
26
29
use std:: mem:: { self , MaybeUninit } ;
27
30
use std:: ptr;
@@ -109,6 +112,53 @@ impl<T> Default for TypedArena<T> {
109
112
}
110
113
}
111
114
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
+
112
162
impl < T > TypedArena < T > {
113
163
/// Allocates an object in the `TypedArena`, returning a reference to it.
114
164
#[ inline]
@@ -183,10 +233,10 @@ impl<T> TypedArena<T> {
183
233
}
184
234
}
185
235
236
+ /// General case implementation for `alloc_from_iter()`.
186
237
#[ 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 ( ) ;
190
240
if vec. is_empty ( ) {
191
241
return & mut [ ] ;
192
242
}
@@ -201,6 +251,14 @@ impl<T> TypedArena<T> {
201
251
}
202
252
}
203
253
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
+
204
262
/// Grows the arena.
205
263
#[ inline( never) ]
206
264
#[ cold]
0 commit comments