1
1
use core:: fmt;
2
2
use core:: iter:: { FusedIterator , TrustedLen , TrustedRandomAccess , TrustedRandomAccessNoCoerce } ;
3
+ use core:: mem:: MaybeUninit ;
3
4
use core:: ops:: Try ;
4
5
5
6
use super :: { count, wrap_index, RingSlices } ;
@@ -12,7 +13,7 @@ use super::{count, wrap_index, RingSlices};
12
13
/// [`iter`]: super::VecDeque::iter
13
14
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
14
15
pub struct Iter < ' a , T : ' a > {
15
- pub ( crate ) ring : & ' a [ T ] ,
16
+ pub ( crate ) ring : & ' a [ MaybeUninit < T > ] ,
16
17
pub ( crate ) tail : usize ,
17
18
pub ( crate ) head : usize ,
18
19
}
@@ -21,7 +22,15 @@ pub struct Iter<'a, T: 'a> {
21
22
impl < T : fmt:: Debug > fmt:: Debug for Iter < ' _ , T > {
22
23
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
23
24
let ( front, back) = RingSlices :: ring_slices ( self . ring , self . head , self . tail ) ;
24
- f. debug_tuple ( "Iter" ) . field ( & front) . field ( & back) . finish ( )
25
+ // Safety:
26
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
27
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
28
+ unsafe {
29
+ f. debug_tuple ( "Iter" )
30
+ . field ( & MaybeUninit :: slice_assume_init_ref ( front) )
31
+ . field ( & MaybeUninit :: slice_assume_init_ref ( back) )
32
+ . finish ( )
33
+ }
25
34
}
26
35
}
27
36
@@ -44,7 +53,10 @@ impl<'a, T> Iterator for Iter<'a, T> {
44
53
}
45
54
let tail = self . tail ;
46
55
self . tail = wrap_index ( self . tail . wrapping_add ( 1 ) , self . ring . len ( ) ) ;
47
- unsafe { Some ( self . ring . get_unchecked ( tail) ) }
56
+ // Safety:
57
+ // - `self.tail` in a ring buffer is always a valid index.
58
+ // - `self.head` and `self.tail` equality is checked above.
59
+ unsafe { Some ( self . ring . get_unchecked ( tail) . assume_init_ref ( ) ) }
48
60
}
49
61
50
62
#[ inline]
@@ -58,8 +70,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
58
70
F : FnMut ( Acc , Self :: Item ) -> Acc ,
59
71
{
60
72
let ( front, back) = RingSlices :: ring_slices ( self . ring , self . head , self . tail ) ;
61
- accum = front. iter ( ) . fold ( accum, & mut f) ;
62
- back. iter ( ) . fold ( accum, & mut f)
73
+ // Safety:
74
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
75
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
76
+ unsafe {
77
+ accum = MaybeUninit :: slice_assume_init_ref ( front) . iter ( ) . fold ( accum, & mut f) ;
78
+ MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) . fold ( accum, & mut f)
79
+ }
63
80
}
64
81
65
82
fn try_fold < B , F , R > ( & mut self , init : B , mut f : F ) -> R
@@ -70,17 +87,19 @@ impl<'a, T> Iterator for Iter<'a, T> {
70
87
{
71
88
let ( mut iter, final_res) ;
72
89
if self . tail <= self . head {
73
- // single slice self.ring[self.tail..self.head]
74
- iter = self . ring [ self . tail ..self . head ] . iter ( ) ;
90
+ // Safety: single slice self.ring[self.tail..self.head] is initialized.
91
+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( & self . ring [ self . tail ..self . head ] ) }
92
+ . iter ( ) ;
75
93
final_res = iter. try_fold ( init, & mut f) ;
76
94
} else {
77
- // two slices: self.ring[self.tail..], self.ring[..self.head]
95
+ // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
78
96
let ( front, back) = self . ring . split_at ( self . tail ) ;
79
- let mut back_iter = back. iter ( ) ;
97
+
98
+ let mut back_iter = unsafe { MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) } ;
80
99
let res = back_iter. try_fold ( init, & mut f) ;
81
100
let len = self . ring . len ( ) ;
82
101
self . tail = ( self . ring . len ( ) - back_iter. len ( ) ) & ( len - 1 ) ;
83
- iter = front[ ..self . head ] . iter ( ) ;
102
+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( & front[ ..self . head ] ) . iter ( ) } ;
84
103
final_res = iter. try_fold ( res?, & mut f) ;
85
104
}
86
105
self . tail = self . head - iter. len ( ) ;
@@ -109,7 +128,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
109
128
// that is in bounds.
110
129
unsafe {
111
130
let idx = wrap_index ( self . tail . wrapping_add ( idx) , self . ring . len ( ) ) ;
112
- self . ring . get_unchecked ( idx)
131
+ self . ring . get_unchecked ( idx) . assume_init_ref ( )
113
132
}
114
133
}
115
134
}
@@ -122,16 +141,24 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
122
141
return None ;
123
142
}
124
143
self . head = wrap_index ( self . head . wrapping_sub ( 1 ) , self . ring . len ( ) ) ;
125
- unsafe { Some ( self . ring . get_unchecked ( self . head ) ) }
144
+ // Safety:
145
+ // - `self.head` in a ring buffer is always a valid index.
146
+ // - `self.head` and `self.tail` equality is checked above.
147
+ unsafe { Some ( self . ring . get_unchecked ( self . head ) . assume_init_ref ( ) ) }
126
148
}
127
149
128
150
fn rfold < Acc , F > ( self , mut accum : Acc , mut f : F ) -> Acc
129
151
where
130
152
F : FnMut ( Acc , Self :: Item ) -> Acc ,
131
153
{
132
154
let ( front, back) = RingSlices :: ring_slices ( self . ring , self . head , self . tail ) ;
133
- accum = back. iter ( ) . rfold ( accum, & mut f) ;
134
- front. iter ( ) . rfold ( accum, & mut f)
155
+ // Safety:
156
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
157
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
158
+ unsafe {
159
+ accum = MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) . rfold ( accum, & mut f) ;
160
+ MaybeUninit :: slice_assume_init_ref ( front) . iter ( ) . rfold ( accum, & mut f)
161
+ }
135
162
}
136
163
137
164
fn try_rfold < B , F , R > ( & mut self , init : B , mut f : F ) -> R
@@ -142,16 +169,20 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
142
169
{
143
170
let ( mut iter, final_res) ;
144
171
if self . tail <= self . head {
145
- // single slice self.ring[self.tail..self.head]
146
- iter = self . ring [ self . tail ..self . head ] . iter ( ) ;
172
+ // Safety: single slice self.ring[self.tail..self.head] is initialized.
173
+ iter = unsafe {
174
+ MaybeUninit :: slice_assume_init_ref ( & self . ring [ self . tail ..self . head ] ) . iter ( )
175
+ } ;
147
176
final_res = iter. try_rfold ( init, & mut f) ;
148
177
} else {
149
- // two slices: self.ring[self.tail..], self.ring[..self.head]
178
+ // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
150
179
let ( front, back) = self . ring . split_at ( self . tail ) ;
151
- let mut front_iter = front[ ..self . head ] . iter ( ) ;
180
+
181
+ let mut front_iter =
182
+ unsafe { MaybeUninit :: slice_assume_init_ref ( & front[ ..self . head ] ) . iter ( ) } ;
152
183
let res = front_iter. try_rfold ( init, & mut f) ;
153
184
self . head = front_iter. len ( ) ;
154
- iter = back. iter ( ) ;
185
+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) } ;
155
186
final_res = iter. try_rfold ( res?, & mut f) ;
156
187
}
157
188
self . head = self . tail + iter. len ( ) ;
0 commit comments