@@ -17,6 +17,17 @@ use core::ops::Deref;
1717use core:: ptr:: { self , NonNull } ;
1818use core:: slice:: { self } ;
1919
20+ macro non_null {
21+ ( mut $place: expr, $t: ident) => { {
22+ #![ allow( unused_unsafe) ] // we're sometimes used within an unsafe block
23+ unsafe { & mut * ptr:: addr_of_mut!( $place) . cast :: < NonNull < $t> > ( ) }
24+ } } ,
25+ ( $place: expr, $t: ident) => { {
26+ #![ allow( unused_unsafe) ] // we're sometimes used within an unsafe block
27+ unsafe { * ptr:: addr_of!( $place) . cast :: < NonNull < $t> > ( ) }
28+ } } ,
29+ }
30+
2031/// An iterator that moves out of a vector.
2132 ///
2233/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec)
@@ -40,10 +51,12 @@ pub struct IntoIter<
4051 // the drop impl reconstructs a RawVec from buf, cap and alloc
4152 // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop
4253 pub ( super ) alloc : ManuallyDrop < A > ,
43- pub ( super ) ptr : * const T ,
44- pub ( super ) end : * const T , // If T is a ZST, this is actually ptr+len. This encoding is picked so that
45- // ptr == end is a quick test for the Iterator being empty, that works
46- // for both ZST and non-ZST.
54+ pub ( super ) ptr : NonNull < T > ,
55+ /// If T is a ZST, this is actually ptr+len. This encoding is picked so that
56+ /// ptr == end is a quick test for the Iterator being empty, that works
57+ /// for both ZST and non-ZST.
58+ /// For non-ZSTs the pointer is treated as `NonNull<T>`
59+ pub ( super ) end : * const T ,
4760}
4861
4962#[ stable( feature = "vec_intoiter_debug" , since = "1.13.0" ) ]
@@ -67,7 +80,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
6780 /// ```
6881 #[ stable( feature = "vec_into_iter_as_slice" , since = "1.15.0" ) ]
6982 pub fn as_slice ( & self ) -> & [ T ] {
70- unsafe { slice:: from_raw_parts ( self . ptr , self . len ( ) ) }
83+ unsafe { slice:: from_raw_parts ( self . ptr . as_ptr ( ) , self . len ( ) ) }
7184 }
7285
7386 /// Returns the remaining items of this iterator as a mutable slice.
@@ -96,7 +109,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
96109 }
97110
98111 fn as_raw_mut_slice ( & mut self ) -> * mut [ T ] {
99- ptr:: slice_from_raw_parts_mut ( self . ptr as * mut T , self . len ( ) )
112+ ptr:: slice_from_raw_parts_mut ( self . ptr . as_ptr ( ) , self . len ( ) )
100113 }
101114
102115 /// Drops remaining elements and relinquishes the backing allocation.
@@ -123,7 +136,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
123136 // this creates less assembly
124137 self . cap = 0 ;
125138 self . buf = unsafe { NonNull :: new_unchecked ( RawVec :: NEW . ptr ( ) ) } ;
126- self . ptr = self . buf . as_ptr ( ) ;
139+ self . ptr = self . buf ;
127140 self . end = self . buf . as_ptr ( ) ;
128141
129142 // Dropping the remaining elements can panic, so this needs to be
@@ -137,7 +150,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
137150 pub ( crate ) fn forget_remaining_elements ( & mut self ) {
138151 // For the ZST case, it is crucial that we mutate `end` here, not `ptr`.
139152 // `ptr` must stay aligned, while `end` may be unaligned.
140- self . end = self . ptr ;
153+ self . end = self . ptr . as_ptr ( ) ;
141154 }
142155
143156 #[ cfg( not( no_global_oom_handling) ) ]
@@ -159,7 +172,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
159172 // say that they're all at the beginning of the "allocation".
160173 0 ..this. len ( )
161174 } else {
162- this. ptr . sub_ptr ( buf) ..this. end . sub_ptr ( buf)
175+ this. ptr . sub_ptr ( this . buf ) ..this. end . sub_ptr ( buf)
163176 } ;
164177 let cap = this. cap ;
165178 let alloc = ManuallyDrop :: take ( & mut this. alloc ) ;
@@ -186,37 +199,43 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
186199
187200 #[ inline]
188201 fn next ( & mut self ) -> Option < T > {
189- if self . ptr == self . end {
190- None
191- } else if T :: IS_ZST {
192- // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
193- // reducing the `end`.
194- self . end = self . end . wrapping_byte_sub ( 1 ) ;
195-
196- // Make up a value of this ZST.
197- Some ( unsafe { mem:: zeroed ( ) } )
202+ if T :: IS_ZST {
203+ if self . ptr . as_ptr ( ) . cast_const ( ) == self . end {
204+ None
205+ } else {
206+ // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
207+ // reducing the `end`.
208+ self . end = self . end . wrapping_byte_sub ( 1 ) ;
209+
210+ // Make up a value of this ZST.
211+ Some ( unsafe { mem:: zeroed ( ) } )
212+ }
198213 } else {
199- let old = self . ptr ;
200- self . ptr = unsafe { self . ptr . add ( 1 ) } ;
214+ if self . ptr == non_null ! ( self . end, T ) {
215+ None
216+ } else {
217+ let old = self . ptr ;
218+ self . ptr = unsafe { old. add ( 1 ) } ;
201219
202- Some ( unsafe { ptr:: read ( old) } )
220+ Some ( unsafe { ptr:: read ( old. as_ptr ( ) ) } )
221+ }
203222 }
204223 }
205224
206225 #[ inline]
207226 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
208227 let exact = if T :: IS_ZST {
209- self . end . addr ( ) . wrapping_sub ( self . ptr . addr ( ) )
228+ self . end . addr ( ) . wrapping_sub ( self . ptr . as_ptr ( ) . addr ( ) )
210229 } else {
211- unsafe { self . end . sub_ptr ( self . ptr ) }
230+ unsafe { non_null ! ( self . end, T ) . sub_ptr ( self . ptr ) }
212231 } ;
213232 ( exact, Some ( exact) )
214233 }
215234
216235 #[ inline]
217236 fn advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZeroUsize > {
218237 let step_size = self . len ( ) . min ( n) ;
219- let to_drop = ptr:: slice_from_raw_parts_mut ( self . ptr as * mut T , step_size) ;
238+ let to_drop = ptr:: slice_from_raw_parts_mut ( self . ptr . as_ptr ( ) , step_size) ;
220239 if T :: IS_ZST {
221240 // See `next` for why we sub `end` here.
222241 self . end = self . end . wrapping_byte_sub ( step_size) ;
@@ -258,7 +277,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
258277 // Safety: `len` indicates that this many elements are available and we just checked that
259278 // it fits into the array.
260279 unsafe {
261- ptr:: copy_nonoverlapping ( self . ptr , raw_ary. as_mut_ptr ( ) as * mut T , len) ;
280+ ptr:: copy_nonoverlapping ( self . ptr . as_ptr ( ) , raw_ary. as_mut_ptr ( ) as * mut T , len) ;
262281 self . forget_remaining_elements ( ) ;
263282 return Err ( array:: IntoIter :: new_unchecked ( raw_ary, 0 ..len) ) ;
264283 }
@@ -267,7 +286,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
267286 // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize
268287 // the array.
269288 return unsafe {
270- ptr:: copy_nonoverlapping ( self . ptr , raw_ary. as_mut_ptr ( ) as * mut T , N ) ;
289+ ptr:: copy_nonoverlapping ( self . ptr . as_ptr ( ) , raw_ary. as_mut_ptr ( ) as * mut T , N ) ;
271290 self . ptr = self . ptr . add ( N ) ;
272291 Ok ( raw_ary. transpose ( ) . assume_init ( ) )
273292 } ;
@@ -286,7 +305,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
286305 // that `T: Copy` so reading elements from the buffer doesn't invalidate
287306 // them for `Drop`.
288307 unsafe {
289- if T :: IS_ZST { mem:: zeroed ( ) } else { ptr:: read ( self . ptr . add ( i) ) }
308+ if T :: IS_ZST { mem:: zeroed ( ) } else { ptr:: read ( self . ptr . add ( i) . as_ptr ( ) ) }
290309 }
291310 }
292311}
@@ -295,18 +314,25 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
295314impl < T , A : Allocator > DoubleEndedIterator for IntoIter < T , A > {
296315 #[ inline]
297316 fn next_back ( & mut self ) -> Option < T > {
298- if self . end == self . ptr {
299- None
300- } else if T :: IS_ZST {
301- // See above for why 'ptr.offset' isn't used
302- self . end = self . end . wrapping_byte_sub ( 1 ) ;
303-
304- // Make up a value of this ZST.
305- Some ( unsafe { mem:: zeroed ( ) } )
317+ if T :: IS_ZST {
318+ if self . end == self . ptr . as_ptr ( ) . cast_const ( ) {
319+ None
320+ } else {
321+ // See above for why 'ptr.offset' isn't used
322+ self . end = self . end . wrapping_byte_sub ( 1 ) ;
323+
324+ // Make up a value of this ZST.
325+ Some ( unsafe { mem:: zeroed ( ) } )
326+ }
306327 } else {
307- self . end = unsafe { self . end . sub ( 1 ) } ;
328+ if non_null ! ( self . end, T ) == self . ptr {
329+ None
330+ } else {
331+ let new_end = unsafe { non_null ! ( self . end, T ) . sub ( 1 ) } ;
332+ * non_null ! ( mut self . end, T ) = new_end;
308333
309- Some ( unsafe { ptr:: read ( self . end ) } )
334+ Some ( unsafe { ptr:: read ( new_end. as_ptr ( ) ) } )
335+ }
310336 }
311337 }
312338
@@ -332,7 +358,11 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
332358#[ stable( feature = "rust1" , since = "1.0.0" ) ]
333359impl < T , A : Allocator > ExactSizeIterator for IntoIter < T , A > {
334360 fn is_empty ( & self ) -> bool {
335- self . ptr == self . end
361+ if T :: IS_ZST {
362+ self . ptr . as_ptr ( ) . cast_const ( ) == self . end
363+ } else {
364+ self . ptr == non_null ! ( self . end, T )
365+ }
336366 }
337367}
338368
0 commit comments