]> git.proxmox.com Git - rustc.git/blame - library/core/src/iter/range.rs
New upstream version 1.52.1+dfsg1
[rustc.git] / library / core / src / iter / range.rs
CommitLineData
f9f354fc 1use crate::char;
48663c56
XL
2use crate::convert::TryFrom;
3use crate::mem;
6a06907d 4use crate::ops::{self, Try};
a7813a04 5
c30ab7b3 6use super::{FusedIterator, TrustedLen};
a7813a04 7
f9f354fc 8/// Objects that have a notion of *successor* and *predecessor* operations.
a7813a04 9///
f9f354fc
XL
10/// The *successor* operation moves towards values that compare greater.
11/// The *predecessor* operation moves towards values that compare lesser.
12///
13/// # Safety
14///
15/// This trait is `unsafe` because its implementation must be correct for
16/// the safety of `unsafe trait TrustedLen` implementations, and the results
17/// of using this trait can otherwise be trusted by `unsafe` code to be correct
18/// and fulfill the listed obligations.
19#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
20pub unsafe trait Step: Clone + PartialOrd + Sized {
21 /// Returns the number of *successor* steps required to get from `start` to `end`.
22 ///
23 /// Returns `None` if the number of steps would overflow `usize`
24 /// (or is infinite, or if `end` would never be reached).
25 ///
26 /// # Invariants
27 ///
28 /// For any `a`, `b`, and `n`:
29 ///
30 /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward_checked(&a, n) == Some(b)`
31 /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&a, n) == Some(a)`
32 /// * `steps_between(&a, &b) == Some(n)` only if `a <= b`
33 /// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b`
34 /// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
3dfed10e 35 /// this is the case when it would require more than `usize::MAX` steps to get to `b`
f9f354fc 36 /// * `steps_between(&a, &b) == None` if `a > b`
041b39d2 37 fn steps_between(start: &Self, end: &Self) -> Option<usize>;
3157f602 38
f9f354fc
XL
39 /// Returns the value that would be obtained by taking the *successor*
40 /// of `self` `count` times.
41 ///
42 /// If this would overflow the range of values supported by `Self`, returns `None`.
43 ///
44 /// # Invariants
45 ///
46 /// For any `a`, `n`, and `m`:
47 ///
48 /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))`
60c5eb7d 49 ///
f9f354fc
XL
50 /// For any `a`, `n`, and `m` where `n + m` does not overflow:
51 ///
52 /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, n + m)`
53 ///
54 /// For any `a` and `n`:
55 ///
56 /// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))`
57 /// * Corollary: `Step::forward_checked(&a, 0) == Some(a)`
58 #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
59 fn forward_checked(start: Self, count: usize) -> Option<Self>;
3157f602 60
f9f354fc
XL
61 /// Returns the value that would be obtained by taking the *successor*
62 /// of `self` `count` times.
63 ///
64 /// If this would overflow the range of values supported by `Self`,
65 /// this function is allowed to panic, wrap, or saturate.
66 /// The suggested behavior is to panic when debug assertions are enabled,
67 /// and to wrap or saturate otherwise.
68 ///
69 /// Unsafe code should not rely on the correctness of behavior after overflow.
60c5eb7d 70 ///
f9f354fc
XL
71 /// # Invariants
72 ///
73 /// For any `a`, `n`, and `m`, where no overflow occurs:
74 ///
75 /// * `Step::forward(Step::forward(a, n), m) == Step::forward(a, n + m)`
76 ///
77 /// For any `a` and `n`, where no overflow occurs:
78 ///
79 /// * `Step::forward_checked(a, n) == Some(Step::forward(a, n))`
80 /// * `Step::forward(a, n) == (0..n).fold(a, |x, _| Step::forward(x, 1))`
81 /// * Corollary: `Step::forward(a, 0) == a`
82 /// * `Step::forward(a, n) >= a`
83 /// * `Step::backward(Step::forward(a, n), n) == a`
84 #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
85 fn forward(start: Self, count: usize) -> Self {
86 Step::forward_checked(start, count).expect("overflow in `Step::forward`")
87 }
3157f602 88
f9f354fc
XL
89 /// Returns the value that would be obtained by taking the *successor*
90 /// of `self` `count` times.
91 ///
92 /// # Safety
93 ///
94 /// It is undefined behavior for this operation to overflow the
95 /// range of values supported by `Self`. If you cannot guarantee that this
96 /// will not overflow, use `forward` or `forward_checked` instead.
97 ///
98 /// # Invariants
99 ///
100 /// For any `a`:
101 ///
102 /// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)`
103 /// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`,
104 /// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`.
105 ///
106 /// For any `a` and `n`, where no overflow occurs:
107 ///
108 /// * `Step::forward_unchecked(a, n)` is equivalent to `Step::forward(a, n)`
109 #[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")]
110 unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
111 Step::forward(start, count)
112 }
3157f602 113
5869c6ff 114 /// Returns the value that would be obtained by taking the *predecessor*
f9f354fc
XL
115 /// of `self` `count` times.
116 ///
117 /// If this would overflow the range of values supported by `Self`, returns `None`.
118 ///
119 /// # Invariants
120 ///
121 /// For any `a`, `n`, and `m`:
122 ///
123 /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::backward_checked(a, x))`
124 /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == try { Step::backward_checked(a, n.checked_add(m)?) }`
125 ///
126 /// For any `a` and `n`:
127 ///
128 /// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(&x, 1))`
129 /// * Corollary: `Step::backward_checked(&a, 0) == Some(a)`
130 #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
131 fn backward_checked(start: Self, count: usize) -> Option<Self>;
041b39d2 132
f9f354fc
XL
133 /// Returns the value that would be obtained by taking the *predecessor*
134 /// of `self` `count` times.
135 ///
136 /// If this would overflow the range of values supported by `Self`,
137 /// this function is allowed to panic, wrap, or saturate.
138 /// The suggested behavior is to panic when debug assertions are enabled,
139 /// and to wrap or saturate otherwise.
140 ///
141 /// Unsafe code should not rely on the correctness of behavior after overflow.
142 ///
143 /// # Invariants
144 ///
145 /// For any `a`, `n`, and `m`, where no overflow occurs:
146 ///
147 /// * `Step::backward(Step::backward(a, n), m) == Step::backward(a, n + m)`
148 ///
149 /// For any `a` and `n`, where no overflow occurs:
150 ///
151 /// * `Step::backward_checked(a, n) == Some(Step::backward(a, n))`
152 /// * `Step::backward(a, n) == (0..n).fold(a, |x, _| Step::backward(x, 1))`
153 /// * Corollary: `Step::backward(a, 0) == a`
154 /// * `Step::backward(a, n) <= a`
155 /// * `Step::forward(Step::backward(a, n), n) == a`
156 #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
157 fn backward(start: Self, count: usize) -> Self {
158 Step::backward_checked(start, count).expect("overflow in `Step::backward`")
159 }
dc9dc135 160
f9f354fc
XL
161 /// Returns the value that would be obtained by taking the *predecessor*
162 /// of `self` `count` times.
163 ///
164 /// # Safety
165 ///
166 /// It is undefined behavior for this operation to overflow the
167 /// range of values supported by `Self`. If you cannot guarantee that this
168 /// will not overflow, use `backward` or `backward_checked` instead.
169 ///
170 /// # Invariants
171 ///
172 /// For any `a`:
173 ///
174 /// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)`
175 /// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`,
176 /// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`.
177 ///
178 /// For any `a` and `n`, where no overflow occurs:
179 ///
180 /// * `Step::backward_unchecked(a, n)` is equivalent to `Step::backward(a, n)`
181 #[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")]
182 unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
183 Step::backward(start, count)
dc9dc135 184 }
041b39d2
XL
185}
186
187// These are still macro-generated because the integer literals resolve to different types.
188macro_rules! step_identical_methods {
189 () => {
190 #[inline]
f9f354fc 191 unsafe fn forward_unchecked(start: Self, n: usize) -> Self {
f035d41b
XL
192 // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
193 unsafe { start.unchecked_add(n as Self) }
041b39d2
XL
194 }
195
196 #[inline]
f9f354fc 197 unsafe fn backward_unchecked(start: Self, n: usize) -> Self {
f035d41b
XL
198 // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
199 unsafe { start.unchecked_sub(n as Self) }
041b39d2
XL
200 }
201
202 #[inline]
5869c6ff 203 #[allow(arithmetic_overflow)]
6a06907d 204 #[rustc_inherit_overflow_checks]
f9f354fc
XL
205 fn forward(start: Self, n: usize) -> Self {
206 // In debug builds, trigger a panic on overflow.
207 // This should optimize completely out in release builds.
208 if Self::forward_checked(start, n).is_none() {
6a06907d 209 let _ = Self::MAX + 1;
f9f354fc
XL
210 }
211 // Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`.
212 start.wrapping_add(n as Self)
041b39d2
XL
213 }
214
215 #[inline]
5869c6ff 216 #[allow(arithmetic_overflow)]
6a06907d 217 #[rustc_inherit_overflow_checks]
f9f354fc
XL
218 fn backward(start: Self, n: usize) -> Self {
219 // In debug builds, trigger a panic on overflow.
220 // This should optimize completely out in release builds.
221 if Self::backward_checked(start, n).is_none() {
6a06907d 222 let _ = Self::MIN - 1;
f9f354fc
XL
223 }
224 // Do wrapping math to allow e.g. `Step::backward(127i8, 255)`.
225 start.wrapping_sub(n as Self)
041b39d2 226 }
f9f354fc 227 };
a7813a04
XL
228}
229
f9f354fc
XL
230macro_rules! step_integer_impls {
231 {
232 narrower than or same width as usize:
233 $( [ $u_narrower:ident $i_narrower:ident ] ),+;
234 wider than usize:
235 $( [ $u_wider:ident $i_wider:ident ] ),+;
236 } => {
237 $(
238 #[allow(unreachable_patterns)]
239 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
240 unsafe impl Step for $u_narrower {
241 step_identical_methods!();
242
243 #[inline]
244 fn steps_between(start: &Self, end: &Self) -> Option<usize> {
245 if *start <= *end {
246 // This relies on $u_narrower <= usize
247 Some((*end - *start) as usize)
248 } else {
249 None
250 }
a7813a04 251 }
3157f602 252
f9f354fc
XL
253 #[inline]
254 fn forward_checked(start: Self, n: usize) -> Option<Self> {
255 match Self::try_from(n) {
256 Ok(n) => start.checked_add(n),
257 Err(_) => None, // if n is out of range, `unsigned_start + n` is too
258 }
259 }
260
261 #[inline]
262 fn backward_checked(start: Self, n: usize) -> Option<Self> {
263 match Self::try_from(n) {
264 Ok(n) => start.checked_sub(n),
265 Err(_) => None, // if n is out of range, `unsigned_start - n` is too
266 }
041b39d2 267 }
3157f602
XL
268 }
269
dc9dc135 270 #[allow(unreachable_patterns)]
f9f354fc
XL
271 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
272 unsafe impl Step for $i_narrower {
273 step_identical_methods!();
274
275 #[inline]
276 fn steps_between(start: &Self, end: &Self) -> Option<usize> {
277 if *start <= *end {
278 // This relies on $i_narrower <= usize
279 //
280 // Casting to isize extends the width but preserves the sign.
281 // Use wrapping_sub in isize space and cast to usize to compute
282 // the difference that may not fit inside the range of isize.
283 Some((*end as isize).wrapping_sub(*start as isize) as usize)
284 } else {
285 None
286 }
dc9dc135 287 }
dc9dc135 288
f9f354fc
XL
289 #[inline]
290 fn forward_checked(start: Self, n: usize) -> Option<Self> {
291 match $u_narrower::try_from(n) {
292 Ok(n) => {
293 // Wrapping handles cases like
294 // `Step::forward(-120_i8, 200) == Some(80_i8)`,
295 // even though 200 is out of range for i8.
296 let wrapped = start.wrapping_add(n as Self);
297 if wrapped >= start {
298 Some(wrapped)
299 } else {
300 None // Addition overflowed
301 }
302 }
303 // If n is out of range of e.g. u8,
304 // then it is bigger than the entire range for i8 is wide
305 // so `any_i8 + n` necessarily overflows i8.
306 Err(_) => None,
307 }
308 }
309
310 #[inline]
311 fn backward_checked(start: Self, n: usize) -> Option<Self> {
312 match $u_narrower::try_from(n) {
313 Ok(n) => {
314 // Wrapping handles cases like
315 // `Step::forward(-120_i8, 200) == Some(80_i8)`,
316 // even though 200 is out of range for i8.
317 let wrapped = start.wrapping_sub(n as Self);
318 if wrapped <= start {
319 Some(wrapped)
320 } else {
321 None // Subtraction overflowed
322 }
323 }
324 // If n is out of range of e.g. u8,
325 // then it is bigger than the entire range for i8 is wide
326 // so `any_i8 - n` necessarily overflows i8.
327 Err(_) => None,
328 }
a7813a04
XL
329 }
330 }
f9f354fc 331 )+
3157f602 332
f9f354fc 333 $(
ea8adc8c 334 #[allow(unreachable_patterns)]
f9f354fc
XL
335 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
336 unsafe impl Step for $u_wider {
337 step_identical_methods!();
338
339 #[inline]
340 fn steps_between(start: &Self, end: &Self) -> Option<usize> {
341 if *start <= *end {
342 usize::try_from(*end - *start).ok()
343 } else {
344 None
041b39d2 345 }
f9f354fc
XL
346 }
347
348 #[inline]
349 fn forward_checked(start: Self, n: usize) -> Option<Self> {
350 start.checked_add(n as Self)
351 }
352
353 #[inline]
354 fn backward_checked(start: Self, n: usize) -> Option<Self> {
355 start.checked_sub(n as Self)
041b39d2 356 }
3157f602
XL
357 }
358
dc9dc135 359 #[allow(unreachable_patterns)]
f9f354fc
XL
360 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
361 unsafe impl Step for $i_wider {
362 step_identical_methods!();
363
364 #[inline]
365 fn steps_between(start: &Self, end: &Self) -> Option<usize> {
366 if *start <= *end {
367 match end.checked_sub(*start) {
368 Some(result) => usize::try_from(result).ok(),
369 // If the difference is too big for e.g. i128,
370 // it's also gonna be too big for usize with fewer bits.
371 None => None,
dc9dc135 372 }
f9f354fc
XL
373 } else {
374 None
dc9dc135 375 }
f9f354fc
XL
376 }
377
378 #[inline]
379 fn forward_checked(start: Self, n: usize) -> Option<Self> {
380 start.checked_add(n as Self)
381 }
382
383 #[inline]
384 fn backward_checked(start: Self, n: usize) -> Option<Self> {
385 start.checked_sub(n as Self)
dc9dc135
XL
386 }
387 }
f9f354fc
XL
388 )+
389 };
390}
dc9dc135 391
f9f354fc
XL
392#[cfg(target_pointer_width = "64")]
393step_integer_impls! {
394 narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [u64 i64], [usize isize];
395 wider than usize: [u128 i128];
396}
397
398#[cfg(target_pointer_width = "32")]
399step_integer_impls! {
400 narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [usize isize];
401 wider than usize: [u64 i64], [u128 i128];
402}
403
404#[cfg(target_pointer_width = "16")]
405step_integer_impls! {
406 narrower than or same width as usize: [u8 i8], [u16 i16], [usize isize];
407 wider than usize: [u32 i32], [u64 i64], [u128 i128];
a7813a04
XL
408}
409
f9f354fc
XL
410#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
411unsafe impl Step for char {
412 #[inline]
413 fn steps_between(&start: &char, &end: &char) -> Option<usize> {
414 let start = start as u32;
415 let end = end as u32;
416 if start <= end {
417 let count = end - start;
418 if start < 0xD800 && 0xE000 <= end {
419 usize::try_from(count - 0x800).ok()
420 } else {
421 usize::try_from(count).ok()
422 }
423 } else {
424 None
425 }
426 }
427
428 #[inline]
429 fn forward_checked(start: char, count: usize) -> Option<char> {
430 let start = start as u32;
431 let mut res = Step::forward_checked(start, count)?;
432 if start < 0xD800 && 0xD800 <= res {
433 res = Step::forward_checked(res, 0x800)?;
434 }
435 if res <= char::MAX as u32 {
436 // SAFETY: res is a valid unicode scalar
437 // (below 0x110000 and not in 0xD800..0xE000)
438 Some(unsafe { char::from_u32_unchecked(res) })
439 } else {
440 None
441 }
442 }
443
444 #[inline]
445 fn backward_checked(start: char, count: usize) -> Option<char> {
446 let start = start as u32;
447 let mut res = Step::backward_checked(start, count)?;
448 if start >= 0xE000 && 0xE000 > res {
449 res = Step::backward_checked(res, 0x800)?;
450 }
451 // SAFETY: res is a valid unicode scalar
452 // (below 0x110000 and not in 0xD800..0xE000)
453 Some(unsafe { char::from_u32_unchecked(res) })
454 }
455
456 #[inline]
457 unsafe fn forward_unchecked(start: char, count: usize) -> char {
458 let start = start as u32;
f035d41b
XL
459 // SAFETY: the caller must guarantee that this doesn't overflow
460 // the range of values for a char.
461 let mut res = unsafe { Step::forward_unchecked(start, count) };
f9f354fc 462 if start < 0xD800 && 0xD800 <= res {
f035d41b
XL
463 // SAFETY: the caller must guarantee that this doesn't overflow
464 // the range of values for a char.
465 res = unsafe { Step::forward_unchecked(res, 0x800) };
f9f354fc 466 }
f035d41b
XL
467 // SAFETY: because of the previous contract, this is guaranteed
468 // by the caller to be a valid char.
469 unsafe { char::from_u32_unchecked(res) }
f9f354fc
XL
470 }
471
472 #[inline]
473 unsafe fn backward_unchecked(start: char, count: usize) -> char {
474 let start = start as u32;
f035d41b
XL
475 // SAFETY: the caller must guarantee that this doesn't overflow
476 // the range of values for a char.
477 let mut res = unsafe { Step::backward_unchecked(start, count) };
f9f354fc 478 if start >= 0xE000 && 0xE000 > res {
f035d41b
XL
479 // SAFETY: the caller must guarantee that this doesn't overflow
480 // the range of values for a char.
481 res = unsafe { Step::backward_unchecked(res, 0x800) };
f9f354fc 482 }
f035d41b
XL
483 // SAFETY: because of the previous contract, this is guaranteed
484 // by the caller to be a valid char.
485 unsafe { char::from_u32_unchecked(res) }
f9f354fc
XL
486 }
487}
a7813a04 488
a7813a04
XL
489macro_rules! range_exact_iter_impl {
490 ($($t:ty)*) => ($(
491 #[stable(feature = "rust1", since = "1.0.0")]
492 impl ExactSizeIterator for ops::Range<$t> { }
c30ab7b3
SL
493 )*)
494}
a7813a04 495
c30ab7b3
SL
496macro_rules! range_incl_exact_iter_impl {
497 ($($t:ty)*) => ($(
0531ce1d 498 #[stable(feature = "inclusive_range", since = "1.26.0")]
a7813a04
XL
499 impl ExactSizeIterator for ops::RangeInclusive<$t> { }
500 )*)
501}
502
503#[stable(feature = "rust1", since = "1.0.0")]
041b39d2 504impl<A: Step> Iterator for ops::Range<A> {
a7813a04
XL
505 type Item = A;
506
507 #[inline]
508 fn next(&mut self) -> Option<A> {
509 if self.start < self.end {
f9f354fc 510 // SAFETY: just checked precondition
f9f354fc
XL
511 let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
512 Some(mem::replace(&mut self.start, n))
a7813a04
XL
513 } else {
514 None
515 }
516 }
517
518 #[inline]
519 fn size_hint(&self) -> (usize, Option<usize>) {
f9f354fc
XL
520 if self.start < self.end {
521 let hint = Step::steps_between(&self.start, &self.end);
522 (hint.unwrap_or(usize::MAX), hint)
523 } else {
524 (0, Some(0))
a7813a04
XL
525 }
526 }
041b39d2
XL
527
528 #[inline]
529 fn nth(&mut self, n: usize) -> Option<A> {
f9f354fc 530 if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
041b39d2 531 if plus_n < self.end {
f035d41b
XL
532 // SAFETY: just checked precondition
533 self.start = unsafe { Step::forward_unchecked(plus_n.clone(), 1) };
dfeec247 534 return Some(plus_n);
041b39d2
XL
535 }
536 }
537
538 self.start = self.end.clone();
539 None
540 }
2c00a5a8
XL
541
542 #[inline]
543 fn last(mut self) -> Option<A> {
544 self.next_back()
545 }
546
547 #[inline]
548 fn min(mut self) -> Option<A> {
549 self.next()
550 }
551
552 #[inline]
553 fn max(mut self) -> Option<A> {
554 self.next_back()
555 }
a7813a04
XL
556}
557
c30ab7b3 558// These macros generate `ExactSizeIterator` impls for various range types.
c30ab7b3 559//
f9f354fc
XL
560// * `ExactSizeIterator::len` is required to always return an exact `usize`,
561// so no range can be longer than `usize::MAX`.
562// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`.
563// For integer types in `RangeInclusive<_>`
564// this is the case for types *strictly narrower* than `usize`
565// since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`.
566range_exact_iter_impl! {
567 usize u8 u16
568 isize i8 i16
569
570 // These are incorect per the reasoning above,
571 // but removing them would be a breaking change as they were stabilized in Rust 1.0.0.
572 // So e.g. `(0..66_000_u32).len()` for example will compile without error or warnings
573 // on 16-bit platforms, but continue to give a wrong result.
574 u32
575 i32
576}
577range_incl_exact_iter_impl! {
578 u8
579 i8
580
581 // These are incorect per the reasoning above,
582 // but removing them would be a breaking change as they were stabilized in Rust 1.26.0.
583 // So e.g. `(0..=u16::MAX).len()` for example will compile without error or warnings
584 // on 16-bit platforms, but continue to give a wrong result.
585 u16
586 i16
587}
a7813a04
XL
588
589#[stable(feature = "rust1", since = "1.0.0")]
041b39d2 590impl<A: Step> DoubleEndedIterator for ops::Range<A> {
a7813a04
XL
591 #[inline]
592 fn next_back(&mut self) -> Option<A> {
593 if self.start < self.end {
f035d41b
XL
594 // SAFETY: just checked precondition
595 self.end = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
a7813a04
XL
596 Some(self.end.clone())
597 } else {
598 None
599 }
600 }
dc9dc135
XL
601
602 #[inline]
603 fn nth_back(&mut self, n: usize) -> Option<A> {
f9f354fc 604 if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
dc9dc135 605 if minus_n > self.start {
f035d41b
XL
606 // SAFETY: just checked precondition
607 self.end = unsafe { Step::backward_unchecked(minus_n, 1) };
dfeec247 608 return Some(self.end.clone());
dc9dc135
XL
609 }
610 }
611
612 self.end = self.start.clone();
613 None
614 }
a7813a04
XL
615}
616
f9f354fc
XL
617#[unstable(feature = "trusted_len", issue = "37572")]
618unsafe impl<A: Step> TrustedLen for ops::Range<A> {}
619
0531ce1d 620#[stable(feature = "fused", since = "1.26.0")]
041b39d2 621impl<A: Step> FusedIterator for ops::Range<A> {}
9e0c209e 622
a7813a04 623#[stable(feature = "rust1", since = "1.0.0")]
041b39d2 624impl<A: Step> Iterator for ops::RangeFrom<A> {
a7813a04
XL
625 type Item = A;
626
627 #[inline]
628 fn next(&mut self) -> Option<A> {
f9f354fc
XL
629 let n = Step::forward(self.start.clone(), 1);
630 Some(mem::replace(&mut self.start, n))
a7813a04 631 }
7cac9316
XL
632
633 #[inline]
634 fn size_hint(&self) -> (usize, Option<usize>) {
635 (usize::MAX, None)
636 }
041b39d2
XL
637
638 #[inline]
639 fn nth(&mut self, n: usize) -> Option<A> {
f9f354fc
XL
640 let plus_n = Step::forward(self.start.clone(), n);
641 self.start = Step::forward(plus_n.clone(), 1);
041b39d2
XL
642 Some(plus_n)
643 }
a7813a04
XL
644}
645
0531ce1d 646#[stable(feature = "fused", since = "1.26.0")]
041b39d2 647impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
9e0c209e 648
2c00a5a8
XL
649#[unstable(feature = "trusted_len", issue = "37572")]
650unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}
651
0531ce1d 652#[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2 653impl<A: Step> Iterator for ops::RangeInclusive<A> {
a7813a04
XL
654 type Item = A;
655
656 #[inline]
657 fn next(&mut self) -> Option<A> {
74b04a01 658 if self.is_empty() {
8faf50e0 659 return None;
a7813a04 660 }
8faf50e0 661 let is_iterating = self.start < self.end;
8faf50e0 662 Some(if is_iterating {
f9f354fc 663 // SAFETY: just checked precondition
f9f354fc 664 let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
8faf50e0
XL
665 mem::replace(&mut self.start, n)
666 } else {
74b04a01 667 self.exhausted = true;
8faf50e0
XL
668 self.start.clone()
669 })
a7813a04
XL
670 }
671
672 #[inline]
673 fn size_hint(&self) -> (usize, Option<usize>) {
8faf50e0 674 if self.is_empty() {
7cac9316
XL
675 return (0, Some(0));
676 }
a7813a04 677
041b39d2 678 match Step::steps_between(&self.start, &self.end) {
7cac9316 679 Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
532ac7d7 680 None => (usize::MAX, None),
a7813a04
XL
681 }
682 }
041b39d2
XL
683
684 #[inline]
685 fn nth(&mut self, n: usize) -> Option<A> {
74b04a01 686 if self.is_empty() {
8faf50e0
XL
687 return None;
688 }
689
f9f354fc 690 if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
48663c56 691 use crate::cmp::Ordering::*;
041b39d2
XL
692
693 match plus_n.partial_cmp(&self.end) {
694 Some(Less) => {
f9f354fc 695 self.start = Step::forward(plus_n.clone(), 1);
9fa01778 696 return Some(plus_n);
041b39d2
XL
697 }
698 Some(Equal) => {
74b04a01
XL
699 self.start = plus_n.clone();
700 self.exhausted = true;
9fa01778 701 return Some(plus_n);
041b39d2
XL
702 }
703 _ => {}
704 }
705 }
706
74b04a01
XL
707 self.start = self.end.clone();
708 self.exhausted = true;
041b39d2
XL
709 None
710 }
2c00a5a8 711
9fa01778
XL
712 #[inline]
713 fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
714 where
dfeec247
XL
715 Self: Sized,
716 F: FnMut(B, Self::Item) -> R,
717 R: Try<Ok = B>,
9fa01778 718 {
9fa01778 719 if self.is_empty() {
29967ef6 720 return try { init };
9fa01778
XL
721 }
722
723 let mut accum = init;
724
725 while self.start < self.end {
f035d41b
XL
726 // SAFETY: just checked precondition
727 let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
9fa01778
XL
728 let n = mem::replace(&mut self.start, n);
729 accum = f(accum, n)?;
730 }
731
74b04a01 732 self.exhausted = true;
9fa01778
XL
733
734 if self.start == self.end {
735 accum = f(accum, self.start.clone())?;
736 }
737
29967ef6 738 try { accum }
9fa01778
XL
739 }
740
f9f354fc
XL
741 #[inline]
742 fn fold<B, F>(mut self, init: B, f: F) -> B
743 where
744 Self: Sized,
745 F: FnMut(B, Self::Item) -> B,
746 {
747 #[inline]
748 fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
749 move |acc, x| Ok(f(acc, x))
750 }
751
752 self.try_fold(init, ok(f)).unwrap()
753 }
754
2c00a5a8
XL
755 #[inline]
756 fn last(mut self) -> Option<A> {
757 self.next_back()
758 }
759
760 #[inline]
761 fn min(mut self) -> Option<A> {
762 self.next()
763 }
764
765 #[inline]
766 fn max(mut self) -> Option<A> {
767 self.next_back()
768 }
a7813a04
XL
769}
770
0531ce1d 771#[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2 772impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
a7813a04
XL
773 #[inline]
774 fn next_back(&mut self) -> Option<A> {
74b04a01 775 if self.is_empty() {
8faf50e0 776 return None;
2c00a5a8 777 }
8faf50e0 778 let is_iterating = self.start < self.end;
8faf50e0 779 Some(if is_iterating {
f035d41b
XL
780 // SAFETY: just checked precondition
781 let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
8faf50e0
XL
782 mem::replace(&mut self.end, n)
783 } else {
74b04a01 784 self.exhausted = true;
8faf50e0
XL
785 self.end.clone()
786 })
a7813a04 787 }
9fa01778 788
dc9dc135
XL
789 #[inline]
790 fn nth_back(&mut self, n: usize) -> Option<A> {
74b04a01 791 if self.is_empty() {
dc9dc135
XL
792 return None;
793 }
794
f9f354fc 795 if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
dc9dc135
XL
796 use crate::cmp::Ordering::*;
797
798 match minus_n.partial_cmp(&self.start) {
799 Some(Greater) => {
f9f354fc 800 self.end = Step::backward(minus_n.clone(), 1);
dc9dc135
XL
801 return Some(minus_n);
802 }
803 Some(Equal) => {
74b04a01
XL
804 self.end = minus_n.clone();
805 self.exhausted = true;
dc9dc135
XL
806 return Some(minus_n);
807 }
808 _ => {}
809 }
810 }
811
74b04a01
XL
812 self.end = self.start.clone();
813 self.exhausted = true;
dc9dc135
XL
814 None
815 }
816
9fa01778 817 #[inline]
dfeec247
XL
818 fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
819 where
820 Self: Sized,
821 F: FnMut(B, Self::Item) -> R,
822 R: Try<Ok = B>,
9fa01778 823 {
9fa01778 824 if self.is_empty() {
29967ef6 825 return try { init };
9fa01778
XL
826 }
827
828 let mut accum = init;
829
830 while self.start < self.end {
f035d41b
XL
831 // SAFETY: just checked precondition
832 let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
9fa01778
XL
833 let n = mem::replace(&mut self.end, n);
834 accum = f(accum, n)?;
835 }
836
74b04a01 837 self.exhausted = true;
9fa01778
XL
838
839 if self.start == self.end {
840 accum = f(accum, self.start.clone())?;
841 }
842
29967ef6 843 try { accum }
9fa01778 844 }
f9f354fc
XL
845
846 #[inline]
847 fn rfold<B, F>(mut self, init: B, f: F) -> B
848 where
849 Self: Sized,
850 F: FnMut(B, Self::Item) -> B,
851 {
852 #[inline]
853 fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
854 move |acc, x| Ok(f(acc, x))
855 }
856
857 self.try_rfold(init, ok(f)).unwrap()
858 }
a7813a04
XL
859}
860
f9f354fc
XL
861#[unstable(feature = "trusted_len", issue = "37572")]
862unsafe impl<A: Step> TrustedLen for ops::RangeInclusive<A> {}
863
0531ce1d 864#[stable(feature = "fused", since = "1.26.0")]
041b39d2 865impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}