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 upRedesign the std::iter::Step trait, tweak related iterator impls for ranges #43127
Conversation
rust-highfive
assigned
aturon
Jul 8, 2017
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 @aturon (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. |
This was referenced Jul 8, 2017
frewsxcv
added
the
T-libs
label
Jul 9, 2017
SimonSapin
force-pushed the
SimonSapin:ranges
branch
2 times, most recently
from
d6e1fd7
to
24cd69a
Jul 9, 2017
This comment has been minimized.
This comment has been minimized.
|
https://travis-ci.org/rust-lang/rust/jobs/251678510
|
This comment has been minimized.
This comment has been minimized.
|
Merging this as-is would make the situation in #43124 even worse — the speed of Edit: However, changing the implementation of #[inline]
fn forward(&self, n: usize) -> Option<Self> {
match Self::try_from(n) {
Ok(n_converted) => self.checked_add(n_converted),
Err(_) => None, // if n is out of range, `something_unsigned + n` is too
}
}to: #[inline]
fn forward(&self, n: usize) -> Option<Self> {
if n <= u16::MAX as usize {
self.checked_add(n as u16)
} else {
None
}
}would immediately fix #43124 (speed becomes ~4µs/iter). I don't understand what LLVM is thinking Edit²: Putting the |
oyvindln
referenced this pull request
Jul 9, 2017
Closed
Collect<Vec<u16>> from range doesn't optimize well. #43124
This comment has been minimized.
This comment has been minimized.
The impl for TryFrom casts the value to i/u128 to check if it's in range, maybe that is something that could cause issues as the 128-bit types are somewhat special. |
This comment has been minimized.
This comment has been minimized.
|
I think the current state of this PR is about the amount of effort I’m willing to put into this at the moment. If anyone would like to pick it up and push on the optimization front, feel free. (I think going through 128-bit ints in |
This comment has been minimized.
This comment has been minimized.
|
o.O I'm not sure why travis is failing like this with linking problems: https://travis-ci.org/rust-lang/rust/jobs/251678510#L1044 I tried restarting that job to make sure it wasn't something intermittent but it just failed in the same way again... do you have any ideas why this might be happening for this PR @SimonSapin ? |
carols10cents
added
the
S-waiting-on-review
label
Jul 10, 2017
This comment has been minimized.
This comment has been minimized.
Surely this couId be better worded. I had to read this docstring very carefully to convince myself that it does indeed follow the typical rust semantics of half-open ranges, and that e.g. |
This comment has been minimized.
This comment has been minimized.
|
@carols10cents On IRC @eddyb said it’s probably because intrinsics for u128 divison use a range iterator but are not allowed to link to panic code, and this PR adds calls to So it sounds like this needs more work to have correct overflow semantics without using panicking code. @ExpHP I don’t mind rewriting this if you have a suggestion how. I avoided talking about addition and subtraction because |
This comment has been minimized.
This comment has been minimized.
I would suggest making reference to the "length of the range |
oyvindln
referenced this pull request
Jul 10, 2017
Open
Tracking issue for TryFrom/TryInto traits #33417
carols10cents
added
S-waiting-on-author
and removed
S-waiting-on-review
labels
Jul 10, 2017
oyvindln
referenced this pull request
Jul 12, 2017
Closed
Add inline annotations and avoid 128-bit where it's not needed in TryFrom + tests for xsize/x128 #43194
scottmcm
reviewed
Jul 15, 2017
| // This seems redundant with a similar comparison that `Step::steps_between` | ||
| // implementations need to do, but it separates the `start > end` case from `start == end`. | ||
| // `steps_between` returns `Some(0)` in both of these cases, but we only want to add 1 | ||
| // in the latter. |
This comment has been minimized.
This comment has been minimized.
scottmcm
Jul 15, 2017
•
Member
Should steps_between perhaps instead return something like Result<Option<usize>, Unreachable>? Might make the documentation for the method easier to write, too.
scottmcm
reviewed
Jul 15, 2017
| /// Returns `None` if this would overflow the range of values supported by the type `Self`. | ||
| /// | ||
| /// Note: `step_count == 1` is a common case, | ||
| /// used for example in `Iterator::next` for ranges. |
This comment has been minimized.
This comment has been minimized.
scottmcm
Jul 15, 2017
•
Member
Would it be worth a fn forward_one(&self) -> Option<Self> { self.forward(1) } (or call it successor, perhaps, like the comment here does) so the common case is overridable if needed? I suppose it's always addable later if needed.
scottmcm
reviewed
Jul 15, 2017
| @@ -280,7 +353,8 @@ impl<A: Step> Iterator for ops::RangeFrom<A> { | |||
|
|
|||
| #[inline] | |||
| fn next(&mut self) -> Option<A> { | |||
| let mut n = self.start.add_one(); | |||
| // Overflow can happen here. Panic when it does. | |||
| let mut n = self.start.forward(1).expect("overflow in RangeFrom::next"); | |||
This comment has been minimized.
This comment has been minimized.
scottmcm
Jul 15, 2017
Member
IIRC this used to only panic in debug, right?
I like the change, but it might need to be called out in documentation somewhere.
This comment has been minimized.
This comment has been minimized.
|
Thanks for picking this up, @SimonSapin! The trait looks way better now. Some general musings on the trait:
|
This comment has been minimized.
This comment has been minimized.
So things that have a successor but no predecessor? Yes, this would require a trait separate from |
This comment has been minimized.
This comment has been minimized.
|
friendly ping to keep this on your radar @SimonSapin ! |
SimonSapin
added some commits
Jul 6, 2017
SimonSapin
added some commits
Jul 7, 2017
SimonSapin
force-pushed the
SimonSapin:ranges
branch
from
24cd69a
to
0ac7fca
Jul 24, 2017
This comment has been minimized.
This comment has been minimized.
|
My understanding is that the main concern at this point is performance, and I wrote:
As to the CI failure, it might be fixed by #43258. I’ve pushed a rebase to trigger a new build. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
added
S-waiting-on-review
and removed
S-waiting-on-author
labels
Jul 27, 2017
This comment has been minimized.
This comment has been minimized.
|
ping @aturon for a review! |
This comment has been minimized.
This comment has been minimized.
|
This needs some more work that I’m not planning to do soon, closing to make that clear. Hopefully someone else can take over.
|
SimonSapin commentedJul 8, 2017
•
edited
CC #42168
The trait is now:
Arithmetic and overflow handling with multiple integer types of different widths and signedness is tricky, careful review would be appreciated.
Other changes:
TrustedLenis now implemented for ranges ofall integer typesallT: Steptypes.Stepis now anunsafe traitas a consequence.ExactSizeIteratorimpls forRangeInclusive<u16>andRangeInclusive<i16>as they are incorrect on 16-bit platforms. CC #43086 (comment)1...0after the last iteration. Instead increment or decrement similarly to other iterations. If that would cause overflow, decrement/increment the other bound instead.(usize::MAX, None)instead of(0, None)insize_hintwhen the exact result would overflowusize.