Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upImplement Vec::drain from RFC 574 #24781
Conversation
rust-highfive
assigned
brson
Apr 24, 2015
This comment has been minimized.
This comment has been minimized.
|
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @brson (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. The way Github handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see CONTRIBUTING.md for more information. |
bluss
force-pushed the
bluss:vec-drain-range
branch
from
a6a721a
to
aa9e061
Apr 24, 2015
This comment has been minimized.
This comment has been minimized.
|
r? @aturon |
rust-highfive
assigned
aturon
and unassigned
brson
Apr 24, 2015
alexcrichton
reviewed
Apr 24, 2015
| Range, | ||
| RangeTo, | ||
| RangeFrom | ||
| }; |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
Stylistically the compiler doesn't tend to put an import-per-line like this but instead use multiple use statements.
This comment has been minimized.
This comment has been minimized.
bluss
Apr 24, 2015
Author
Contributor
One line with {RangeFull, Range, ..} for all the ranges would be the usual style then?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
Indeed! The wrapping (to a new import) just happens if it runs over 80 chars
alexcrichton
reviewed
Apr 24, 2015
| /// A draining iterator for `Vec<T>`. | ||
| #[unstable(feature = "collections", reason = "recently added")] | ||
| pub struct Drain<'a, T: 'a> | ||
| { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
Style-wise the compiler typically puts this brace on the prior line (for here and the functions and such below)
This comment has been minimized.
This comment has been minimized.
bluss
Apr 24, 2015
Author
Contributor
Thanks, I should have checked for this! I'm somewhat of a rebel and I know it
alexcrichton
reviewed
Apr 24, 2015
| }; | ||
| self.set_len(0); | ||
| // set self.vec length's to start, to be safe in case Drain is leaked | ||
| self.set_len(start); |
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Apr 24, 2015
| /// Current remaining range to remove | ||
| iter: slice::Iter<'a, T>, | ||
| vec: *mut Vec<T>, | ||
| _marker: PhantomData<&'a mut Vec<T>>, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
Perhaps this could eschew the PhantomData by storing slice::IterMut<'a, T>?
This comment has been minimized.
This comment has been minimized.
bluss
Apr 24, 2015
Author
Contributor
The old PR had a discussion about that. This would affect variance, but I'm not clear on what's right. We use the iterator during iteration but then deref the *mut Vec once in the destructor to use it as &mut Vec.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
Ah that's why I was thinking of using IterMut instead of Iter (to take out the mutable borrow as opposed to a shared one). Although I'm not sure what effect that would have on this in terms of variance.
This comment has been minimized.
This comment has been minimized.
bluss
Apr 25, 2015
Author
Contributor
I've done my variance homework and IterMut seems fine. Both &mut Vec<T> and &mut T (in IterMut) should have the same implications (invariant in T).
This comment has been minimized.
This comment has been minimized.
bluss
Apr 25, 2015
Author
Contributor
I see why covariant in T is really possible here too. We could do that too. Just removing values from the Vec would allow it, but it feels shaky (and I don't know any example where it mattes in practice).
alexcrichton
reviewed
Apr 24, 2015
| None => None, | ||
| Some(elt) => { | ||
| unsafe { | ||
| Some(ptr::read(elt as *const _)) | ||
| } | ||
| } | ||
| } |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
This may be a good spot for a map:
self.iter.next_back().map(|ptr| unsafe {
ptr::read(ptr)
})
alexcrichton
reviewed
Apr 24, 2015
| /// Index of tail to preserve | ||
| tail_start: usize, | ||
| /// Length of tail | ||
| tail_len: usize, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
In the interest of saving space, either length or start can be derived from the other, right?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
Oh wait nevermind, the vector's length is "inaccurate" so it can't be used!
This comment has been minimized.
This comment has been minimized.
bluss
Apr 24, 2015
Author
Contributor
The vector's temporary length stores another necessary field -- the original starting point of the range we are removing.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bluss
Apr 24, 2015
Author
Contributor
I'm not going to attempt the drop flag without advice because I'm not up to date with how filling drop interacts with that.
alexcrichton
reviewed
Apr 24, 2015
| } | ||
|
|
||
| unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {} | ||
| unsafe impl<'a, T: Send> Send for Drain<'a, T> {} | ||
|
|
||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| impl<'a, T> Iterator for Drain<'a, T> { | ||
| impl<'a, T> Iterator for Drain<'a, T> | ||
| { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 24, 2015
Member
There's a few next-line { characters that should move up here and below (just skimming the diff)
bluss
force-pushed the
bluss:vec-drain-range
branch
from
311a374
to
bb12d20
Apr 25, 2015
This comment has been minimized.
This comment has been minimized.
|
I've addressed all review comments, thank you @alexcrichton! Introducing this as unstable gives us leeway to fix it up later, what we could change:
|
alexcrichton
reviewed
Apr 27, 2015
| use core::option::Option::{self, None, Some}; | ||
| use core::ops::{RangeFull, Range, RangeTo, RangeFrom}; | ||
|
|
||
| #[unstable(feature = "collections", reason = "was just added")] |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 27, 2015
Member
On second though, could you apply just one of these stability attributes to the module itself? The instability should be inherited. Additionally, could you give this a name like collections_range as well?
alexcrichton
reviewed
Apr 27, 2015
| /// ``` | ||
| #[inline] | ||
| #[unstable(feature = "collections", |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Apr 27, 2015
Member
While you're at it, could you change the name of this feature to something like collections_drain?
alexcrichton
reviewed
Apr 27, 2015
| end: *const T, | ||
| marker: PhantomData<&'a T>, | ||
| /// A draining iterator for `Vec<T>`. | ||
| #[unstable(feature = "collections", reason = "recently added")] |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Looks great to me, thanks @bluss! After some minor refinements of the feature names here I think this is good to go! |
This comment has been minimized.
This comment has been minimized.
|
I'm excited. I'm working on checking that it compiles and then squashing it together. |
bluss
force-pushed the
bluss:vec-drain-range
branch
from
be84f11
to
6e5f8ce
Apr 27, 2015
This comment has been minimized.
This comment has been minimized.
|
Thanks! Lemme know when it's ready to go and I'll r+ |
bluss
force-pushed the
bluss:vec-drain-range
branch
from
6e5f8ce
to
b7d1ad9
Apr 27, 2015
bluss
force-pushed the
bluss:vec-drain-range
branch
from
b7d1ad9
to
447ef06
Apr 27, 2015
This comment has been minimized.
This comment has been minimized.
|
There, it should be ready. I could have missed something, haven't added new feature flags before. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Apr 28, 2015
This comment has been minimized.
This comment has been minimized.
|
|
bluss
force-pushed the
bluss:vec-drain-range
branch
from
447ef06
to
b475fc7
Apr 28, 2015
This comment has been minimized.
This comment has been minimized.
|
Fixed that test. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
bors
added a commit
that referenced
this pull request
Apr 28, 2015
This comment has been minimized.
This comment has been minimized.
bors
merged commit b475fc7
into
rust-lang:master
Apr 29, 2015
bluss
deleted the
bluss:vec-drain-range
branch
Apr 29, 2015
This comment has been minimized.
This comment has been minimized.
|
So I know I'm starting to sound like a broken record but... use std::collections::Bound;
trait Bounds {
fn start(&self) -> Bound<&T>;
fn end(&self) -> Bound<&T>;
}
impl<T> Bounds for Range<T> {
fn start(&self) -> Bound<&T> { Bound::Included(&self.start) }
fn start(&self) -> Bound<&T> { Bound::Excluded(&self.end) }
}
// ...I suggest adding an |
This comment has been minimized.
This comment has been minimized.
|
I agree it's not ready for stabilization. Specifically the design of the trait over ranges, and then we should impl drain for more collections to see how the API holds up. |
bluss
referenced this pull request
May 1, 2015
Merged
Implement String::drain(range) according to RFC 574 #25028
This comment has been minimized.
This comment has been minimized.
|
|
bluss commentedApr 24, 2015
Implement Vec::drain() from rust-lang/rfcs#574, tracking issue #23055.
This is a big step forward for vector usability. This is an introduction of an API for removing a range of m consecutive elements from a vector, as efficently as possible.
New features:
std::collections::range::RangeArgumentimplemented by all four built-in range types.Vec::drain()to useVec::drain<R: RangeArgument>(R)Implementation notes:
set_lenon the source vector when creating the iterator, to make sure that the part of the vector that will be modified is unreachable. Fix up things in Drain's destructor — but even if it doesn't run, we don't expose any moved-out-from slots of the vector..drain<R>(R)very close to how it is specified in the RFC.usizeindex as a range argument in the RFC is not included. The ranges trait would have to change to accomodate it.Please help me with:
Previous PR and discussion: #23071