Skip to content

specialize Extend for Vec with IntoIter #41191

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

Merged
merged 1 commit into from
Apr 20, 2017

Conversation

seanmonstar
Copy link
Contributor

Before, vec.extend(&other_vec) was quite a bit faster than vec.extend(other_vec). This allows extending by consuming a vec to use the same code as extending from a slice.

@alexcrichton
Copy link
Member

Could this perhaps elide the unsafety by delegating to the other specialization?

@seanmonstar seanmonstar force-pushed the spec-extend-vec-intoiter branch from 4a2f784 to 75e3607 Compare April 11, 2017 18:38
@seanmonstar
Copy link
Contributor Author

@alexcrichton er, of course. Now delegating to extending from slice.

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Collaborator

bors commented Apr 11, 2017

📌 Commit 75e3607 has been approved by alexcrichton

@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Apr 11, 2017
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 12, 2017
…r, r=alexcrichton

specialize Extend for Vec with IntoIter

Before, `vec.extend(&other_vec)` was quite a bit faster than `vec.extend(other_vec)`. This allows extending by consuming a vec to use the same code as extending from a slice.
@frewsxcv
Copy link
Member

@bors r-

Travis found an issue with this

@arielb1
Copy link
Contributor

arielb1 commented Apr 12, 2017

Can't this be a memcpy even when T is not Copy?

@Mark-Simulacrum Mark-Simulacrum added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 14, 2017
@seanmonstar seanmonstar force-pushed the spec-extend-vec-intoiter branch 2 times, most recently from d567538 to ade6fe3 Compare April 14, 2017 17:55
@seanmonstar
Copy link
Contributor Author

@arielb1 I had assumed not, because you'd need to drop items that weren't Copy, but it looks like Vec::append does exactly this.

So, I've refactored to make this make use of the same code as append, and then manually set the iterator at the end. This should mean that items aren't dropped, but the heap space is.

@seanmonstar seanmonstar force-pushed the spec-extend-vec-intoiter branch from ade6fe3 to d7b2906 Compare April 14, 2017 18:13
@arielb1
Copy link
Contributor

arielb1 commented Apr 16, 2017

r? @bluss

@arielb1 arielb1 added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 16, 2017
@arielb1 arielb1 requested a review from bluss April 16, 2017 12:39
Copy link
Member

@bluss bluss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, memcpy is indeed what we do to move ownership of the elements from the iterator's buffer to the vec's. The request for change is basically a style issue, but I thought it was worthwhile.

///
/// Does not drop elements from slice, must be handled by caller.
#[inline]
unsafe fn append_slice(&mut self, other: &[T]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use other here to transfer ownership of the elements, I'd be more comfortable with passing them as other: *mut [T], and it could also be even more clear in the comment that elements are moved from other; especially since elements are not dropped after actual use of the method. (No strong opinion on which *const or *mut to use.)

@carols10cents carols10cents added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 17, 2017
@seanmonstar seanmonstar force-pushed the spec-extend-vec-intoiter branch from d7b2906 to 4d900be Compare April 17, 2017 17:21
@seanmonstar
Copy link
Contributor Author

@bluss updated to fn append_elements(&mut self, other: *const, count: usize).

@alexcrichton
Copy link
Member

Looks great! Could you also add some tests which exercise this specific specialization? (and corner cases like empty vectors, zero-sized types, etc)

@seanmonstar seanmonstar force-pushed the spec-extend-vec-intoiter branch from 4d900be to 94075c4 Compare April 19, 2017 03:34
@seanmonstar
Copy link
Contributor Author

@alexcrichton there were tests for extend, I've added to them tests for zero-sized types and testing that there is no double drop.

other.set_len(0);
}
}

/// Appends a elements to `Self`, without moving.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method does move elements read from other into self's allocation. It should also not talk about dropping, because no T elements need to be dropped or are dropped; they are just moved from being stored in one buffer to the other.

Can the method append_elements use an argument of type *const [T] instead? Coercions from &[T] should make that simple to call in both the calling sites.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Please change this comment to say that it moves the elements, or at least not say without moving, because it is moving them.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated type to *const [T].

I've changed to docs to the suggested, but the original made more sense to me. It's only half moving the elements. It has directly copied them, but the original buffer has not been modified, so if the caller doesn't do something, they'll have copied potentially uncopiable data, and have data unsafety. 🤷‍♂️

@seanmonstar seanmonstar force-pushed the spec-extend-vec-intoiter branch from 94075c4 to f85a533 Compare April 19, 2017 18:57
@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Collaborator

bors commented Apr 20, 2017

📌 Commit f85a533 has been approved by alexcrichton

@bors
Copy link
Collaborator

bors commented Apr 20, 2017

⌛ Testing commit f85a533 with merge 968ae7b...

bors added a commit that referenced this pull request Apr 20, 2017
…ichton

specialize Extend for Vec with IntoIter

Before, `vec.extend(&other_vec)` was quite a bit faster than `vec.extend(other_vec)`. This allows extending by consuming a vec to use the same code as extending from a slice.
@bors
Copy link
Collaborator

bors commented Apr 20, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: alexcrichton
Pushing 968ae7b to master...

@bors bors merged commit f85a533 into rust-lang:master Apr 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants