diff options
| author | bors <bors@rust-lang.org> | 2023-09-16 16:43:31 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-16 16:43:31 +0000 |
| commit | 4514fb98d58eb0bcd65a16266875ef031c373cdf (patch) | |
| tree | d0918179ff6a1ac4532a5e0edfadfd4605563e6e | |
| parent | 409e7f6f21f9728fa1a4a277ed7d5618ba83cfb2 (diff) | |
| parent | 08aa6c9b650ba83b58600d0794bcf0bc8eef7a42 (diff) | |
| download | rust-4514fb98d58eb0bcd65a16266875ef031c373cdf.tar.gz rust-4514fb98d58eb0bcd65a16266875ef031c373cdf.zip | |
Auto merge of #112229 - clarfonthey:range-iter-count, r=dtolnay
Specialize count for range iterators Since `size_hint` is already specialized, it feels apt to specialize `count` as well. Without any specialized version of `ExactSizeIterator::len` or `Step::steps_between`, this feels like a more reliable way of accessing this without having to rely on knowing that `size_hint` is correct. In my case, this is particularly useful to access the `steps_between` implementation for `char` from the standard library without having to compute it manually. I didn't think it was worth modifying the `Step` trait to add a version of `steps_between` that used native overflow checks since this is just doing one subtraction in most cases anyway, and so I decided to make the inclusive version use `checked_add` so it didn't have this lopsided overflow-checks-but-only-sometimes logic.
| -rw-r--r-- | library/core/src/iter/range.rs | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 44feb0a5638..391e03636ab 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -766,6 +766,15 @@ impl<A: Step> Iterator for ops::Range<A> { } #[inline] + fn count(self) -> usize { + if self.start < self.end { + Step::steps_between(&self.start, &self.end).expect("count overflowed usize") + } else { + 0 + } + } + + #[inline] fn nth(&mut self, n: usize) -> Option<A> { self.spec_nth(n) } @@ -1163,6 +1172,17 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> { } #[inline] + fn count(self) -> usize { + if self.is_empty() { + return 0; + } + + Step::steps_between(&self.start, &self.end) + .and_then(|steps| steps.checked_add(1)) + .expect("count overflowed usize") + } + + #[inline] fn nth(&mut self, n: usize) -> Option<A> { if self.is_empty() { return None; |
