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
}
@@ -44,7 +45,10 @@ impl<'a, T> Iterator for Iter<'a, T> {
44
45
}
45
46
let tail = self . tail ;
46
47
self . tail = wrap_index ( self . tail . wrapping_add ( 1 ) , self . ring . len ( ) ) ;
47
- unsafe { Some ( self . ring . get_unchecked ( tail) ) }
48
+ // Safety:
49
+ // - `self.tail` in a ring buffer is always a valid index.
50
+ // - `self.head` and `self.tail` equality is checked above.
51
+ unsafe { Some ( self . ring . get_unchecked ( tail) . assume_init_ref ( ) ) }
48
52
}
49
53
50
54
#[ inline]
@@ -58,8 +62,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
58
62
F : FnMut ( Acc , Self :: Item ) -> Acc ,
59
63
{
60
64
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)
65
+ // Safety:
66
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
67
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
68
+ unsafe {
69
+ accum = MaybeUninit :: slice_assume_init_ref ( front) . iter ( ) . fold ( accum, & mut f) ;
70
+ MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) . fold ( accum, & mut f)
71
+ }
63
72
}
64
73
65
74
fn try_fold < B , F , R > ( & mut self , init : B , mut f : F ) -> R
@@ -70,17 +79,19 @@ impl<'a, T> Iterator for Iter<'a, T> {
70
79
{
71
80
let ( mut iter, final_res) ;
72
81
if self . tail <= self . head {
73
- // single slice self.ring[self.tail..self.head]
74
- iter = self . ring [ self . tail ..self . head ] . iter ( ) ;
82
+ // Safety: single slice self.ring[self.tail..self.head] is initialized.
83
+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( & self . ring [ self . tail ..self . head ] ) }
84
+ . iter ( ) ;
75
85
final_res = iter. try_fold ( init, & mut f) ;
76
86
} else {
77
- // two slices: self.ring[self.tail..], self.ring[..self.head]
87
+ // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
78
88
let ( front, back) = self . ring . split_at ( self . tail ) ;
79
- let mut back_iter = back. iter ( ) ;
89
+
90
+ let mut back_iter = unsafe { MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) } ;
80
91
let res = back_iter. try_fold ( init, & mut f) ;
81
92
let len = self . ring . len ( ) ;
82
93
self . tail = ( self . ring . len ( ) - back_iter. len ( ) ) & ( len - 1 ) ;
83
- iter = front[ ..self . head ] . iter ( ) ;
94
+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( & front[ ..self . head ] ) . iter ( ) } ;
84
95
final_res = iter. try_fold ( res?, & mut f) ;
85
96
}
86
97
self . tail = self . head - iter. len ( ) ;
@@ -109,7 +120,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
109
120
// that is in bounds.
110
121
unsafe {
111
122
let idx = wrap_index ( self . tail . wrapping_add ( idx) , self . ring . len ( ) ) ;
112
- self . ring . get_unchecked ( idx)
123
+ self . ring . get_unchecked ( idx) . assume_init_ref ( )
113
124
}
114
125
}
115
126
}
@@ -122,16 +133,24 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
122
133
return None ;
123
134
}
124
135
self . head = wrap_index ( self . head . wrapping_sub ( 1 ) , self . ring . len ( ) ) ;
125
- unsafe { Some ( self . ring . get_unchecked ( self . head ) ) }
136
+ // Safety:
137
+ // - `self.head` in a ring buffer is always a valid index.
138
+ // - `self.head` and `self.tail` equality is checked above.
139
+ unsafe { Some ( self . ring . get_unchecked ( self . head ) . assume_init_ref ( ) ) }
126
140
}
127
141
128
142
fn rfold < Acc , F > ( self , mut accum : Acc , mut f : F ) -> Acc
129
143
where
130
144
F : FnMut ( Acc , Self :: Item ) -> Acc ,
131
145
{
132
146
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)
147
+ // Safety:
148
+ // - `self.head` and `self.tail` in a ring buffer are always valid indices.
149
+ // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
150
+ unsafe {
151
+ accum = MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) . rfold ( accum, & mut f) ;
152
+ MaybeUninit :: slice_assume_init_ref ( front) . iter ( ) . rfold ( accum, & mut f)
153
+ }
135
154
}
136
155
137
156
fn try_rfold < B , F , R > ( & mut self , init : B , mut f : F ) -> R
@@ -142,16 +161,20 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
142
161
{
143
162
let ( mut iter, final_res) ;
144
163
if self . tail <= self . head {
145
- // single slice self.ring[self.tail..self.head]
146
- iter = self . ring [ self . tail ..self . head ] . iter ( ) ;
164
+ // Safety: single slice self.ring[self.tail..self.head] is initialized.
165
+ iter = unsafe {
166
+ MaybeUninit :: slice_assume_init_ref ( & self . ring [ self . tail ..self . head ] ) . iter ( )
167
+ } ;
147
168
final_res = iter. try_rfold ( init, & mut f) ;
148
169
} else {
149
- // two slices: self.ring[self.tail..], self.ring[..self.head]
170
+ // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
150
171
let ( front, back) = self . ring . split_at ( self . tail ) ;
151
- let mut front_iter = front[ ..self . head ] . iter ( ) ;
172
+
173
+ let mut front_iter =
174
+ unsafe { MaybeUninit :: slice_assume_init_ref ( & front[ ..self . head ] ) . iter ( ) } ;
152
175
let res = front_iter. try_rfold ( init, & mut f) ;
153
176
self . head = front_iter. len ( ) ;
154
- iter = back. iter ( ) ;
177
+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) } ;
155
178
final_res = iter. try_rfold ( res?, & mut f) ;
156
179
}
157
180
self . head = self . tail + iter. len ( ) ;
0 commit comments