Skip to content
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

Implement Vec::splice and String::splice #32355

Closed
wants to merge 1 commit into from

Conversation

SimonSapin
Copy link
Contributor

RFC: rust-lang/rfcs#1432, tracking issue: #32310

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (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. Due to 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 the contribution instructions for more information.

}

// There may be more elements. Use the lower bound as an estimate.
// FIXME: Is the upper bound a better guess? Or something else?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I’d like some other opinions here. Getting this guess wrong either way causes the tail to be moved twice.

  • If we over-estimate (which it the moment only happens if size_hint is incorrect) we reserve more space than necessary in the vector. But that space can still be used later (with further calls to Vec::push and friends). Vec::reserve often over-allocates anyway.
  • If we under-estimate, we allocate a temporary vector and soon drop it.

Maybe over-estimating is better, and this should use the upper bound when it’s Some? (And fall back to the lower bound otherwise.)

Copy link
Member

Choose a reason for hiding this comment

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

Maybe if the optimistic route is only used if Some(lower) == upper, i.e the iterator claims to know its exact size?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If Some(lower) == upper we already use that. If they’re accurate the Vec we then collect is zero-length. The question is what to do when the two bounds are not equal?

// There may be more elements. Use the lower bound as an estimate.
// FIXME: Is the upper bound a better guess? Or something else?
let (lower_bound, _upper_bound) = self.replace_with.size_hint();
if lower_bound > 0 {
Copy link
Member

Choose a reason for hiding this comment

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

This condition lower_bound > 0 could be replaced by lower_bound > 0 && Some(lower_bound) == _upper_bound. Just to clarify what I mean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I see. In that case we’d avoid moving "tail" elements twice, but we’d allocate a temporary Vec in more cases.

@SimonSapin
Copy link
Contributor Author

It may also make sense to rewrite drain to be based on splice (and std::iter::empty) rather than the reverse. In that case, could Drain be a pub type Drain<'a, T> = Splice<'a, Empty<T>> type alias or would it have to be a wrapper struct?

@@ -1301,6 +1301,63 @@ impl String {
}
}

/// Create a splicing iterator that removes the specified range in the string,
Copy link
Contributor

Choose a reason for hiding this comment

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

s/Create/Creates/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All three fixed, thanks.

@SimonSapin
Copy link
Contributor Author

While we’re talking API (#32355 (comment)), should the replace_with argument of String::splice be I: Iterator<Item=char> rather than &str?

@alexcrichton
Copy link
Member

Hm for consistency it seems like you may want that but on the other hand it seems like most of the time you'd want to splice in another slice. It's also arguably less performant as splicing a slice would require decoding and re-encoding utf-8, although perhaps we could recover the performance through specialization?

This may be a good question to have open for stabilization (and the tracking issue), but doesn't necessarily seem like an immediately blocker for landing the PR.

@SimonSapin
Copy link
Contributor Author

There is indeed the UTF-8 round-trip overhead, and also the accuracy loss of size_hint. The lower bound of str:Chars::size_hint is utf8_len / 4.

@alexcrichton
Copy link
Member

Hm the loss of size_hint may be killer for now, perhaps &str can be favored?

@SimonSapin
Copy link
Contributor Author

I’m fine with sticking to &str.

@bors
Copy link
Contributor

bors commented Apr 12, 2016

☔ The latest upstream changes (presumably #32804) made this pull request unmergeable. Please resolve the merge conflicts.

@alexcrichton
Copy link
Member

ping @SimonSapin, any update on this?

@SimonSapin
Copy link
Contributor Author

I still need to write more tests and haven’t taken the time to do it yet. If someone wants to do so before I do, feel free.

@alexcrichton
Copy link
Member

Ok, in that case I'm gonna close this out of inactivity, but feel free to reopen/resubmit once the tests are there!

@solson
Copy link
Member

solson commented Feb 4, 2017

@alexcrichton Is there some way we can advertise this to see if someone wants to work on it? I hate to see merged RFCs go unimplemented for so long.

@alexcrichton
Copy link
Member

@solson an interesting idea! @rust-lang/libs, thoughts?

@glaebhoerl
Copy link
Contributor

There is (or used to be?) a "help wanted" section in TWiR...

@aturon
Copy link
Member

aturon commented Feb 6, 2017

I added a comment to the tracking issue and marked it "help wanted", which (I think?) will lead it to TWiR (@brson?).

We ultimately should do something more persistent and general, maybe on the roadmap tracker.

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 24, 2017
Implement Vec::splice and String::splice (RFC 1432)

RFC: rust-lang/rfcs#1432, tracking issue: rust-lang#32310
A rebase of rust-lang#32355 with a few more tests.

Let me know if you have any ideas for more tests.

cc @SimonSapin
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 24, 2017
Implement Vec::splice and String::splice (RFC 1432)

RFC: rust-lang/rfcs#1432, tracking issue: rust-lang#32310
A rebase of rust-lang#32355 with a few more tests.

Let me know if you have any ideas for more tests.

cc @SimonSapin
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 24, 2017
Implement Vec::splice and String::splice (RFC 1432)

RFC: rust-lang/rfcs#1432, tracking issue: rust-lang#32310
A rebase of rust-lang#32355 with a few more tests.

Let me know if you have any ideas for more tests.

cc @SimonSapin
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 25, 2017
Implement Vec::splice and String::splice (RFC 1432)

RFC: rust-lang/rfcs#1432, tracking issue: rust-lang#32310
A rebase of rust-lang#32355 with a few more tests.

Let me know if you have any ideas for more tests.

cc @SimonSapin
bors added a commit that referenced this pull request Apr 25, 2017
Implement Vec::splice and String::splice (RFC 1432)

RFC: rust-lang/rfcs#1432, tracking issue: #32310
A rebase of #32355 with a few more tests.

Let me know if you have any ideas for more tests.

cc @SimonSapin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants