From dddcbcfeac13c1cf0a262e7d57e14d6588dcadc2 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 6 Apr 2015 11:07:20 -0700 Subject: [PATCH] Fix range performance regression A recent change to the implementation of range iterators meant that, even when stepping by 1, the iterators *always* involved checked arithmetic. This commit reverts to the earlier behavior (while retaining the refactoring into traits). Fixes #24095 cc #24014 --- src/libcore/iter.rs | 47 ++++++++++++++++---------------- src/test/compile-fail/range-1.rs | 1 + 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 939d9b4ab0e..b4fee0ffe2a 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -60,7 +60,7 @@ use self::MinMaxResult::*; use clone::Clone; use cmp; -use cmp::Ord; +use cmp::{Ord, PartialOrd, PartialEq}; use default::Default; use marker; use mem; @@ -2431,7 +2431,7 @@ impl Iterator for Unfold where F: FnMut(&mut St) -> Option { /// two `Step` objects. #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits")] -pub trait Step: Ord { +pub trait Step: PartialOrd { /// Steps `self` if possible. fn step(&self, by: &Self) -> Option; @@ -2598,7 +2598,10 @@ pub fn range_inclusive(start: A, stop: A) -> RangeInclusive #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -impl Iterator for RangeInclusive { +impl Iterator for RangeInclusive where + A: PartialEq + Step + One + Clone, + for<'a> &'a A: Add<&'a A, Output = A> +{ type Item = A; #[inline] @@ -2628,9 +2631,10 @@ impl Iterator for RangeInclusive { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -impl DoubleEndedIterator for RangeInclusive - where A: Step + One + Clone, - for<'a> &'a A: Sub +impl DoubleEndedIterator for RangeInclusive where + A: PartialEq + Step + One + Clone, + for<'a> &'a A: Add<&'a A, Output = A>, + for<'a> &'a A: Sub { #[inline] fn next_back(&mut self) -> Option { @@ -2758,24 +2762,17 @@ macro_rules! range_exact_iter_impl { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for ops::Range { +impl Iterator for ops::Range where + for<'a> &'a A: Add<&'a A, Output = A> +{ type Item = A; #[inline] fn next(&mut self) -> Option { if self.start < self.end { - match self.start.step(&A::one()) { - Some(mut n) => { - mem::swap(&mut n, &mut self.start); - Some(n) - }, - None => { - let mut n = self.end.clone(); - mem::swap(&mut n, &mut self.start); - Some(n) - - } - } + let mut n = &self.start + &A::one(); + mem::swap(&mut n, &mut self.start); + Some(n) } else { None } @@ -2797,6 +2794,7 @@ range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl DoubleEndedIterator for ops::Range where + for<'a> &'a A: Add<&'a A, Output = A>, for<'a> &'a A: Sub<&'a A, Output = A> { #[inline] @@ -2812,15 +2810,16 @@ impl DoubleEndedIterator for ops::Range where #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for ops::RangeFrom { +impl Iterator for ops::RangeFrom where + for<'a> &'a A: Add<&'a A, Output = A> +{ type Item = A; #[inline] fn next(&mut self) -> Option { - self.start.step(&A::one()).map(|mut n| { - mem::swap(&mut n, &mut self.start); - n - }) + let mut n = &self.start + &A::one(); + mem::swap(&mut n, &mut self.start); + Some(n) } } diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index 3ae61722bcf..826e4283ef8 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -19,6 +19,7 @@ pub fn main() { for i in false..true {} //~^ ERROR the trait //~^^ ERROR the trait + //~^^^ ERROR the trait // Unsized type. let arr: &[_] = &[1, 2, 3];