mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
c5faf3a23a
fixed VecDeque::splice() not filling the buffer correctly when resizing the buffer on start = end range This PR fixes rust-lang/rust#151758. The issue came from `Splice::move_tail`, which as joboet pointed out: > The issue is in move_tail, which resizes the buffer, but fails to account for the resulting hole. The problem with reserving more space through `VecDeque`'s `buf.reserve()` is that it doesn't update `VecDeque`'s `head`, which means that this code in `move_tail`: ```rust deque.wrap_copy( deque.to_physical_idx(tail_start), deque.to_physical_idx(new_tail_start), self.tail_len, ); ``` could move over the section of data that `tail_start..tail_start + self.tail_len` of the buffer is supposed to be held at to the incorrect destination since all `.to_physical_idx()` is doing is a wrapping add on the `VecDeque`'s head with the passed in `idx` value. To avoid this I decided to use `VecDeque::reserve` to both allocate more space into the `VecDeque` if necessary and update head appropriately. However, `VecDeque::reserve` internally relies on the `VecDeque`'s `len` field. Earlier in `VecDeque::splice`, it modifies the `VecDeque`'s `len` constructing the drain via `Drain::new` (as it does a `mem::replace` on `deque.len` with the start bound of the passed in `range`). The `VecDeque`'s `len` can also be potentially modified in the earlier `Splice::fill()` call if it does any replacement towards elements within the passed in `range` value for `VecDeque::splice()`. I needed to temporarily restore the `VecDeque`'s `len` to its actual len, so that `VecDeque::reserve` can work properly. Afterward, you can bring back the `VecDeque`'s `len` to what its value was before and fill the gap appropriately with the rest of the `replace_with` content. r? @joboet