-
Notifications
You must be signed in to change notification settings - Fork 14k
add VecDeque::splice #147247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
add VecDeque::splice #147247
Conversation
|
Thanks for working on this! |
|
Sorry I haven't had a chance to look at this, still behind on my reviews r? libs |
|
☔ The latest upstream changes (presumably #148337) made this pull request unmergeable. Please resolve the merge conflicts. |
| return; | ||
| } | ||
|
|
||
| if !self.drain.fill(&mut self.replace_with) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would invalidate source_deque -- can we avoid accidental mis-use by removing that variable, inlining the as_mut() above?
| if true { | ||
| // if !self.drain.fill(tail_start, &mut self.replace_with) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change/comment?
| if let Some(new_item) = replace_with.next() { | ||
| let index = unsafe { self.deque.as_ref() }.to_physical_idx(idx); | ||
| unsafe { self.deque.as_mut().buffer_write(index, new_item) }; | ||
| deque.len += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect this to cause UB -- self.deque.as_mut() has invalidated the earlier deque &mut already at this point?
| // This will set drain.remaining to 0, so its drop won't try to read deallocated memory on | ||
| // drop. | ||
| self.drain.by_ref().for_each(drop); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need something like
rust/library/alloc/src/vec/splice.rs
Line 62 in 87f9dcd
| self.drain.iter = (&[]).iter(); |
| impl<I: Iterator, A: Allocator> ExactSizeIterator for Splice<'_, I, A> {} | ||
|
|
||
| #[unstable(feature = "deque_extend_front", issue = "146975")] | ||
| impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment here and in Vec's Splice pointing at each other?
| return; | ||
| } | ||
|
|
||
| if !self.drain.fill(&mut self.replace_with) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, can you restore the comment from Vec ("First fill the range left by drain().")?
| /// have been moved out. | ||
| /// Fill that range as much as possible with new elements from the `replace_with` iterator. | ||
| /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) | ||
| unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the safety precondition on this method?
| /// This is optimal if: | ||
| /// | ||
| /// * The tail (elements in the deque after `range`) is empty, | ||
| /// * or `replace_with` yields fewer or equal elements than `range`'s length | ||
| /// * or the lower bound of its `size_hint()` is exact. | ||
| /// | ||
| /// Otherwise, a temporary vector is allocated and the tail is moved twice. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a note to the tracking issue to confirm this is accurate? I'm not sure but it feels like there ought to be slightly different conditions vs. Vec, since we have a potentially 'empty' middle to play with...
| unsafe fn move_tail(&mut self, additional: usize) { | ||
| let deque = unsafe { self.deque.as_mut() }; | ||
| let tail_start = deque.len + self.drain_len; | ||
| deque.buf.reserve(tail_start + self.tail_len, additional); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have coverage for this reserve running? Normally growing VecDeque requires extra logic AFAICT, not just reserving the underlying buffer.
Tracking issue: #146975