Skip to content

Commit 93d45a0

Browse files
authored
Rollup merge of rust-lang#72368 - CAD97:rangeto, r=dtolnay
Resolve overflow behavior for RangeFrom This specifies a documented unspecified implementation detail of `RangeFrom` and makes it consistently implement the specified behavior. Specifically, `(u8::MAX).next()` is defined to cause an overflow, and resolve that overflow in the same manner as the `Step::forward` implementation. The inconsistency that has existed is `<RangeFrom as Iterator>::nth`. The existing behavior should be plain to see after rust-lang#69659: the skipping part previously always panicked if it caused an overflow, but the final step (to set up the state for further iteration) has always been debug-checked. The inconsistency, then, is that `RangeFrom::nth` does not implement the same behavior as the naive (and default) implementation of just calling `next` multiple times. This PR aligns `RangeFrom::nth` to have identical behavior to the naive implementation. It also lines up with the standard behavior of primitive math in Rust everywhere else in the language: debug checked overflow. cc @Amanieu --- Followup to rust-lang#69659. Closes rust-lang#25708 (by documenting the panic as intended). The documentation wording is preliminary and can probably be improved. This will probably need an FCP, as it changes observable stable behavior.
2 parents 35db819 + 406852a commit 93d45a0

File tree

2 files changed

+11
-13
lines changed

2 files changed

+11
-13
lines changed

src/libcore/iter/range.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -619,15 +619,7 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
619619

620620
#[inline]
621621
fn nth(&mut self, n: usize) -> Option<A> {
622-
// If we would jump over the maximum value, panic immediately.
623-
// This is consistent with behavior before the Step redesign,
624-
// even though it's inconsistent with n `next` calls.
625-
// To get consistent behavior, change it to use `forward` instead.
626-
// This change should go through FCP separately to the redesign, so is for now left as a
627-
// FIXME: make this consistent
628-
let plus_n =
629-
Step::forward_checked(self.start.clone(), n).expect("overflow in RangeFrom::nth");
630-
// The final step should always be debug-checked.
622+
let plus_n = Step::forward(self.start.clone(), n);
631623
self.start = Step::forward(plus_n.clone(), 1);
632624
Some(plus_n)
633625
}

src/libcore/ops/range.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,16 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
151151
///
152152
/// The `RangeFrom` `start..` contains all values with `x >= start`.
153153
///
154-
/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
155-
/// implementation; if you use an integer range and the integer overflows, it
156-
/// might panic in debug mode or create an endless loop in release mode. **This
157-
/// overflow behavior might change in the future.**
154+
/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
155+
/// data type reaches its numerical limit) is allowed to panic, wrap, or
156+
/// saturate. This behavior is defined by the implementation of the [`Step`]
157+
/// trait. For primitive integers, this follows the normal rules, and respects
158+
/// the overflow checks profile (panic in debug, wrap in release). Note also
159+
/// that overflow happens earlier than you might assume: the overflow happens
160+
/// in the call to `next` that yields the maximum value, as the range must be
161+
/// set to a state to yield the next value.
162+
///
163+
/// [`Step`]: crate::iter::Step
158164
///
159165
/// # Examples
160166
///

0 commit comments

Comments
 (0)