-
Notifications
You must be signed in to change notification settings - Fork 507
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
impl IntoParallelIterator for Range<char> #771
Conversation
I'm not so concerned about 16-bit |
I've updated the PR to just be for
|
Yeah, |
Alright, this should be correctly functional now. (Just that the tests require rustc 1.45 which is currently beta. (I can fix this by just comparing against a constant test case.)) |
The tests before 56ef498 are more obviously correct (as they compare the rayon and std implementations), but said commit compares them against a provided vector... but the impl requires So |
src/range_inclusive.rs
Outdated
where | ||
C: Consumer<Self::Item>, | ||
{ | ||
if let Some((start, end)) = self.bounds() { |
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.
Hmm, bounds()
won't work until Rust 1.45...
FWIW, I was also looking at that function in godbolt, and it works a lot better for char
this way:
if range.size_hint().0 > 0 {
Some((*range.start(), *range.end()))
} else {
None
}
https://rust.godbolt.org/z/8FrRRW
But it does require that we rely on size_hint()
to be correct (like TrustedLen
). I guess this code shouldn't be a hotspot anyway, so it probably doesn't matter.
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.
The correct way to do it would be to use .is_empty()
if/when it stabilizes.
That can be optimized in a followup if necessary/desired, I suppose. I don't think it would be incorrect to use size_hint
here, so long as there's a note about relying on TrustedLen
-like semantics for correctness (but hopefully not safety?).
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.
Side note: oof, there's a unwrap/expect panic still in there. I guess I need to go tweak the impls again to see if I can remove that (as it should be completely unreachable, and if it isn't, that's definitely a bug.)
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.
Yep, the generated asm is a lot better when I add in the missed _unchecked
to next_back
: https://rust.godbolt.org/z/9dviLq
We already have it for next
because I spotted the missed optimization out of the unreachable panicking code, but for some reason I didn't think to check reverse iteration for the same thing.
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 don't think it would be incorrect to use
size_hint
here, so long as there's a note about relying onTrustedLen
-like semantics for correctness (but hopefully not safety?).
There's no safety problem, just start()
and end()
are unspecified when empty.
You can add a test to the build script to get a |
I got that in before you suggested it 🙃 Manually tested that this does engage and work on 1.45. |
For the other |
Added a macro to deduplicate; I think this is what you were suggesting? |
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 think it's good, but I'd like to wait for working Range<char>
to actually reach stable, especially since we're not guarding the implementation of rayon::range::Iter<char>
.
And since I can't help tinkering, here's another option for let start = *range.start();
let end = *range.end();
if start <= end && (start..=end) == *range {
Some((start, end))
} else {
None
} ... assuming |
Here's a comparison of a bunch of the proposed options, with TL;DR: it looks to my untrained eyes that any of the proposed options are roughly equivalent. (Note for |
The commit just pushed uses EDIT: no, I need to go to bed, apparently. The code is definitely still correct with So Waiting until iterable |
…nieu Use step_unchecked more liberally in range iter impls Without these `_unchecked`, these operations on iterators of `char` fail to optimize out the unreachable panicking condition on overflow. cc @cuviper rayon-rs/rayon#771 where this was discovered.
I think we're good for this now, thanks! bors r+ |
Closes #770
Implements both unindexed and indexed parallel iteration for
Range<char>
andRangeInclusive<char>
.