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}
@@ -44,7 +45,10 @@ impl<'a, T> Iterator for Iter<'a, T> {
4445 }
4546 let tail = self . tail ;
4647 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 ( ) ) }
4852 }
4953
5054 #[ inline]
@@ -58,8 +62,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
5862 F : FnMut ( Acc , Self :: Item ) -> Acc ,
5963 {
6064 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+ }
6372 }
6473
6574 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> {
7079 {
7180 let ( mut iter, final_res) ;
7281 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 ( ) ;
7585 final_res = iter. try_fold ( init, & mut f) ;
7686 } 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.
7888 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 ( ) } ;
8091 let res = back_iter. try_fold ( init, & mut f) ;
8192 let len = self . ring . len ( ) ;
8293 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 ( ) } ;
8495 final_res = iter. try_fold ( res?, & mut f) ;
8596 }
8697 self . tail = self . head - iter. len ( ) ;
@@ -109,7 +120,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
109120 // that is in bounds.
110121 unsafe {
111122 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 ( )
113124 }
114125 }
115126}
@@ -122,16 +133,24 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
122133 return None ;
123134 }
124135 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 ( ) ) }
126140 }
127141
128142 fn rfold < Acc , F > ( self , mut accum : Acc , mut f : F ) -> Acc
129143 where
130144 F : FnMut ( Acc , Self :: Item ) -> Acc ,
131145 {
132146 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+ }
135154 }
136155
137156 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> {
142161 {
143162 let ( mut iter, final_res) ;
144163 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+ } ;
147168 final_res = iter. try_rfold ( init, & mut f) ;
148169 } 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.
150171 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 ( ) } ;
152175 let res = front_iter. try_rfold ( init, & mut f) ;
153176 self . head = front_iter. len ( ) ;
154- iter = back. iter ( ) ;
177+ iter = unsafe { MaybeUninit :: slice_assume_init_ref ( back) . iter ( ) } ;
155178 final_res = iter. try_rfold ( res?, & mut f) ;
156179 }
157180 self . head = self . tail + iter. len ( ) ;
0 commit comments