Skip to content

Commit ba134df

Browse files
committed
Specialise the Range::last
1 parent 7b7dcc5 commit ba134df

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

src/libcore/iter/range.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,32 @@ impl<A: Step> Iterator for ops::Range<A> where
249249
})
250250
}
251251

252-
// TODO: last specialisation if `A: Sub` and/or Range<A> is a DoubleEndedIterator.
253-
// so self.end.sub_one() or self.next_back()
252+
#[inline]
253+
fn last(self) -> Option<Self::Item> {
254+
<Self as SpecLast>::last(self)
255+
}
256+
}
257+
258+
trait SpecLast {
259+
type Item;
260+
fn last(self) -> Option<Self::Item>;
261+
}
262+
263+
impl<It> SpecLast for It
264+
where It: Iterator {
265+
type Item = <Self as Iterator>::Item;
266+
#[inline]
267+
default fn last(self) -> Option<Self::Item> {
268+
<Self as Iterator>::last(self)
269+
}
270+
}
271+
272+
impl<It> SpecLast for It
273+
where It: DoubleEndedIterator {
274+
#[inline]
275+
fn last(mut self) -> Option<Self::Item> {
276+
<Self as DoubleEndedIterator>::next_back(&mut self)
277+
}
254278
}
255279

256280
// These macros generate `ExactSizeIterator` impls for various range types.
@@ -319,7 +343,7 @@ impl<A: Step> Iterator for ops::RangeFrom<A> where
319343

320344
#[cold]
321345
fn last(self) -> Option<Self::Item> {
322-
panic!("Iterator::last on a `x..` cannot work")
346+
panic!("Iterator::last on a `x..` will overflow")
323347
}
324348
}
325349

src/libcore/tests/iter.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,12 +1157,6 @@ fn test_usize_range_no_last() {
11571157
assert_eq!((0..).last(), None);
11581158
}
11591159

1160-
#[test]
1161-
#[should_panic]
1162-
fn test_usize_range_no_last() {
1163-
assert_eq!((0..).last(), None);
1164-
}
1165-
11661160
#[test]
11671161
#[should_panic]
11681162
fn test_isize_range_count_oflow() {
@@ -1172,6 +1166,7 @@ fn test_isize_range_count_oflow() {
11721166
#[test]
11731167
fn test_range_last() {
11741168
assert_eq!((0..10).last(), Some(9));
1169+
assert_eq!((0u32..!0).last(), Some(!0 - 1));
11751170
assert_eq!(RangeInclusive { start: 0, end: 10 }.last(), Some(10));
11761171
}
11771172

0 commit comments

Comments
 (0)