19
19
#![ cfg_attr( bootstrap, feature( min_const_generics) ) ]
20
20
#![ feature( min_specialization) ]
21
21
#![ cfg_attr( test, feature( test) ) ]
22
+ #![ feature( rustc_attrs) ]
22
23
23
24
use smallvec:: SmallVec ;
24
25
25
26
use std:: alloc:: Layout ;
26
27
use std:: cell:: { Cell , RefCell } ;
27
28
use std:: cmp;
29
+ use std:: iter:: Cloned ;
28
30
use std:: marker:: { PhantomData , Send } ;
29
31
use std:: mem:: { self , MaybeUninit } ;
30
32
use std:: ptr;
31
- use std:: slice;
33
+ use std:: slice:: { self , Iter } ;
32
34
33
35
#[ inline( never) ]
34
36
#[ cold]
35
37
pub fn cold_path < F : FnOnce ( ) -> R , R > ( f : F ) -> R {
36
38
f ( )
37
39
}
38
40
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
+
39
66
/// An arena that can hold objects of only one type.
40
67
pub struct TypedArena < T > {
41
68
/// A pointer to the next object to be allocated.
@@ -133,6 +160,10 @@ where
133
160
}
134
161
}
135
162
163
+ #[ rustc_unsafe_specialization_marker]
164
+ trait Clonable : Clone { }
165
+ impl < T : Clone > Clonable for T { }
166
+
136
167
impl < T , const N : usize > IterExt < T > for std:: array:: IntoIter < T , N > {
137
168
#[ inline]
138
169
fn alloc_from_iter ( self , arena : & TypedArena < T > ) -> & mut [ T ] {
@@ -167,6 +198,25 @@ impl<T> IterExt<T> for Vec<T> {
167
198
}
168
199
}
169
200
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
+
170
220
impl < A : smallvec:: Array > IterExt < A :: Item > for SmallVec < A > {
171
221
#[ inline]
172
222
fn alloc_from_iter ( mut self , arena : & TypedArena < A :: Item > ) -> & mut [ A :: Item ] {
@@ -489,28 +539,6 @@ impl DroplessArena {
489
539
}
490
540
}
491
541
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
-
514
542
#[ inline]
515
543
pub fn alloc_from_iter < T , I : IntoIterator < Item = T > > ( & self , iter : I ) -> & mut [ T ] {
516
544
let iter = iter. into_iter ( ) ;
@@ -529,7 +557,7 @@ impl DroplessArena {
529
557
}
530
558
531
559
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) }
533
561
}
534
562
( _, _) => {
535
563
cold_path ( move || -> & mut [ T ] {
0 commit comments