@@ -138,8 +138,48 @@ impl<T, A: Allocator> Drain<'_, T, A> {
138138 /// self.deque must be valid.
139139 unsafe fn move_tail ( & mut self , additional : usize ) {
140140 let deque = unsafe { self . deque . as_mut ( ) } ;
141- let tail_start = deque. len + self . drain_len ;
142- deque. buf . reserve ( tail_start + self . tail_len , additional) ;
141+
142+ // `Drain::new` modifies the deque's len (so does `Drain::fill` here)
143+ // directly with the start bound of the range passed into
144+ // `VecDeque::splice`. This causes a few different issue:
145+ // - Most notably, there will be a hole at the end of the
146+ // buffer when our buffer resizes in the case that our
147+ // data wraps around.
148+ // - We cannot use `VecDeque::reserve` directly because
149+ // how it reserves more space and updates the `VecDeque`'s
150+ // `head` field accordingly depends on the `VecDeque`'s
151+ // actual `len`.
152+ // - We cannot just directly modify `VecDeque`'s `len` and
153+ // and call `VecDeque::reserve` afterward because if
154+ // `VecDeque::reserve` panics on capacity overflow,
155+ // well now our `VecDeque`'s head does not get updated
156+ // and we still have a potential hole at the end of the
157+ // buffer.
158+ // Therefore, we manually reserve additional space (if necessary)
159+ // based on calculating the actual `len` of the `VecDeque` and adjust
160+ // `VecDeque`'s len right *after* the panicking region of `VecDeque::reserve`
161+ // (that is `RawVec` `reserve()` call)
162+
163+ let drain_start = deque. len ;
164+ let tail_start = drain_start + self . drain_len ;
165+
166+ // Actual VecDeque's len = drain_start + tail_len + drain_len
167+ let actual_len = drain_start + self . tail_len + self . drain_len ;
168+ let new_cap = actual_len. checked_add ( additional) . expect ( "capacity overflow" ) ;
169+ let old_cap = deque. capacity ( ) ;
170+
171+ if new_cap > old_cap {
172+ deque. buf . reserve ( actual_len, additional) ;
173+ // If new_cap doesn't panic, we can safely set the `VecDeque` len to its
174+ // actual len; this needs to be done in order to set deque.head correctly
175+ // on `VecDeque::handle_capacity_increase`
176+ deque. len = actual_len;
177+ // SAFETY: this cannot panic since our internal buffer's new_cap should
178+ // be bigger than the passed in old_cap
179+ unsafe {
180+ deque. handle_capacity_increase ( old_cap) ;
181+ }
182+ }
143183
144184 let new_tail_start = tail_start + additional;
145185 unsafe {
@@ -149,6 +189,9 @@ impl<T, A: Allocator> Drain<'_, T, A> {
149189 self . tail_len ,
150190 ) ;
151191 }
192+
193+ // revert the `VecDeque` len to what it was before
194+ deque. len = drain_start;
152195 self . drain_len += additional;
153196 }
154197}
0 commit comments