11use core:: fmt;
22use core:: iter:: { FusedIterator , TrustedLen , TrustedRandomAccess , TrustedRandomAccessNoCoerce } ;
3+ use core:: mem:: MaybeUninit ;
34use core:: ops:: Try ;
45
56use super :: { count, wrap_index, RingSlices } ;
@@ -12,7 +13,7 @@ use super::{count, wrap_index, RingSlices};
1213/// [`iter`]: super::VecDeque::iter
1314#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1415pub struct Iter < ' a , T : ' a > {
15- pub ( crate ) ring : & ' a [ T ] ,
16+ pub ( crate ) ring : & ' a [ MaybeUninit < T > ] ,
1617 pub ( crate ) tail : usize ,
1718 pub ( crate ) head : usize ,
1819}
@@ -21,7 +22,15 @@ pub struct Iter<'a, T: 'a> {
2122impl < T : fmt:: Debug > fmt:: Debug for Iter < ' _ , T > {
2223 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
2324 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+ }
2534 }
2635}
2736
@@ -44,7 +53,10 @@ impl<'a, T> Iterator for Iter<'a, T> {
4453 }
4554 let tail = self . tail ;
4655 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 ( ) ) }
4860 }
4961
5062 #[ inline]
@@ -58,8 +70,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
5870 F : FnMut ( Acc , Self :: Item ) -> Acc ,
5971 {
6072 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+ }
6380 }
6481
6582 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> {
7087 {
7188 let ( mut iter, final_res) ;
7289 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 ( ) ;
7593 final_res = iter. try_fold ( init, & mut f) ;
7694 } 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.
7896 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 ( ) } ;
8099 let res = back_iter. try_fold ( init, & mut f) ;
81100 let len = self . ring . len ( ) ;
82101 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 ( ) } ;
84103 final_res = iter. try_fold ( res?, & mut f) ;
85104 }
86105 self . tail = self . head - iter. len ( ) ;
@@ -109,7 +128,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
109128 // that is in bounds.
110129 unsafe {
111130 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 ( )
113132 }
114133 }
115134}
@@ -122,16 +141,24 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
122141 return None ;
123142 }
124143 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 ( ) ) }
126148 }
127149
128150 fn rfold < Acc , F > ( self , mut accum : Acc , mut f : F ) -> Acc
129151 where
130152 F : FnMut ( Acc , Self :: Item ) -> Acc ,
131153 {
132154 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+ }
135162 }
136163
137164 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> {
142169 {
143170 let ( mut iter, final_res) ;
144171 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+ } ;
147176 final_res = iter. try_rfold ( init, & mut f) ;
148177 } 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.
150179 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 ( ) } ;
152183 let res = front_iter. try_rfold ( init, & mut f) ;
153184 self . head = front_iter. len ( ) ;
154- iter = back. iter ( ) ;
185+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) } ;
155186 final_res = iter. try_rfold ( res?, & mut f) ;
156187 }
157188 self . head = self . tail + iter. len ( ) ;
0 commit comments