@@ -213,25 +213,38 @@ impl<T, A: Allocator> IntoIter<T, A> {
213213 // Keep our `Drop` impl from dropping the elements and the allocator
214214 let mut this = ManuallyDrop :: new ( self ) ;
215215
216- // SAFETY: This allocation originally came from a `Vec`, so it passes
217- // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
218- // so the `offset_from_unsigned`s below cannot wrap, and will produce a well-formed
219- // range. `end` ≤ `buf + cap`, so the range will be in-bounds.
220- // Taking `alloc` is ok because nothing else is going to look at it,
221- // since our `Drop` impl isn't going to run so there's no more code.
222- unsafe {
223- let buf = this. buf . as_ptr ( ) ;
224- let initialized = if T :: IS_ZST {
225- // All the pointers are the same for ZSTs, so it's fine to
226- // say that they're all at the beginning of the "allocation".
227- 0 ..this. len ( )
228- } else {
229- this. ptr . offset_from_unsigned ( this. buf ) ..this. end . offset_from_unsigned ( buf)
230- } ;
231- let cap = this. cap ;
232- let alloc = ManuallyDrop :: take ( & mut this. alloc ) ;
233- VecDeque :: from_contiguous_raw_parts_in ( buf, initialized, cap, alloc)
234- }
216+ let buf = this. buf . as_ptr ( ) ;
217+ let initialized = if T :: IS_ZST || this. len ( ) == 0 {
218+ // All the pointers are the same for ZSTs, so it's fine to
219+ // say that they're all at the beginning of the "allocation".
220+ // For non-ZSTs, we have length 0, so we can choose the (empty)
221+ // range to be at the start of the buffer.
222+ //
223+ // Due to `0` ≤ `this.len()` ≤ `this.cap`, the range is well-formed,
224+ // and due to the argument above it spans exactly the elements of
225+ // this iterator. If `cap` ≤ `init.start`, then `cap` = `init.start` = `0`,
226+ // so the range satisfies the requirements of `from_contiguous_raw_parts_in`.
227+ 0 ..this. len ( )
228+ } else {
229+ // SAFETY: `this.ptr` and `this.end` are created via offsets of `this.buf`,
230+ // so they point to the same allocation. We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
231+ // so this cannot wrap, and will produce a well-formed range that spans exactly
232+ // the elements of this iterator.
233+ //
234+ // Additionally, due to `end ≤ buf + cap`, we have `init.start` ≤ `init.end` ≤ `cap`.
235+ // Due to the length check above, `init.start < cap`, so the range satisfies the
236+ // requirements of `from_contiguous_raw_parts_in`.
237+ unsafe { this. ptr . offset_from_unsigned ( this. buf ) ..this. end . offset_from_unsigned ( buf) }
238+ } ;
239+
240+ let cap = this. cap ;
241+ // SAFETY: `this` is forgotten afterwards, so we can move out the allocator.
242+ let alloc = unsafe { ManuallyDrop :: take ( & mut this. alloc ) } ;
243+
244+ // SAFETY: This allocation originally came from a `Vec`, so it satisfies all
245+ // requirements for the `buf` pointer with capacity `cap` allocated in `alloc`.
246+ // Correctness of `initialized` was shown above.
247+ unsafe { VecDeque :: from_contiguous_raw_parts_in ( buf, initialized, cap, alloc) }
235248 }
236249}
237250
0 commit comments