diff options
| author | Nikolai Vazquez <nvazquez1297@gmail.com> | 2017-09-30 10:08:33 -0400 |
|---|---|---|
| committer | Nikolai Vazquez <nvazquez1297@gmail.com> | 2017-09-30 10:08:33 -0400 |
| commit | 4c853adce9103b8bc84cd6b0026bcdc2eed7da31 (patch) | |
| tree | f71af0eb9d7139af598684355e690596721eac1b /src/libcore | |
| parent | d9d877221f65b26e52f49bfc639ef705ff396deb (diff) | |
| parent | c4cca3a72df87def5cb18ff500c643fbff8ad08e (diff) | |
| download | rust-4c853adce9103b8bc84cd6b0026bcdc2eed7da31.tar.gz rust-4c853adce9103b8bc84cd6b0026bcdc2eed7da31.zip | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/libcore')
28 files changed, 954 insertions, 152 deletions
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 827c6354c60..1f16f5b1df3 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -147,40 +147,131 @@ fn bench_for_each_chain_ref_fold(b: &mut Bencher) { }); } -#[bench] -fn bench_flat_map_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000).flat_map(|x| x..x+1000) - .map(black_box) - .sum() - }); + +/// Helper to benchmark `sum` for iterators taken by value which +/// can optimize `fold`, and by reference which cannot. +macro_rules! bench_sums { + ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => { + #[bench] + fn $bench_sum(b: &mut Bencher) { + b.iter(|| -> i64 { + $iter.map(black_box).sum() + }); + } + + #[bench] + fn $bench_ref_sum(b: &mut Bencher) { + b.iter(|| -> i64 { + $iter.map(black_box).by_ref().sum() + }); + } + } } -#[bench] -fn bench_flat_map_ref_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000).flat_map(|x| x..x+1000) - .map(black_box) - .by_ref() - .sum() - }); +bench_sums! { + bench_flat_map_sum, + bench_flat_map_ref_sum, + (0i64..1000).flat_map(|x| x..x+1000) } -#[bench] -fn bench_flat_map_chain_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000000).flat_map(|x| once(x).chain(once(x))) - .map(black_box) - .sum() - }); +bench_sums! { + bench_flat_map_chain_sum, + bench_flat_map_chain_ref_sum, + (0i64..1000000).flat_map(|x| once(x).chain(once(x))) } -#[bench] -fn bench_flat_map_chain_ref_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - (0i64..1000000).flat_map(|x| once(x).chain(once(x))) - .map(black_box) - .by_ref() - .sum() - }); +bench_sums! { + bench_enumerate_sum, + bench_enumerate_ref_sum, + (0i64..1000000).enumerate().map(|(i, x)| x * i as i64) +} + +bench_sums! { + bench_enumerate_chain_sum, + bench_enumerate_chain_ref_sum, + (0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64) +} + +bench_sums! { + bench_filter_sum, + bench_filter_ref_sum, + (0i64..1000000).filter(|x| x % 2 == 0) +} + +bench_sums! { + bench_filter_chain_sum, + bench_filter_chain_ref_sum, + (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0) +} + +bench_sums! { + bench_filter_map_sum, + bench_filter_map_ref_sum, + (0i64..1000000).filter_map(|x| x.checked_mul(x)) +} + +bench_sums! { + bench_filter_map_chain_sum, + bench_filter_map_chain_ref_sum, + (0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x)) +} + +bench_sums! { + bench_fuse_sum, + bench_fuse_ref_sum, + (0i64..1000000).fuse() +} + +bench_sums! { + bench_fuse_chain_sum, + bench_fuse_chain_ref_sum, + (0i64..1000000).chain(0..1000000).fuse() +} + +bench_sums! { + bench_inspect_sum, + bench_inspect_ref_sum, + (0i64..1000000).inspect(|_| {}) +} + +bench_sums! { + bench_inspect_chain_sum, + bench_inspect_chain_ref_sum, + (0i64..1000000).chain(0..1000000).inspect(|_| {}) +} + +bench_sums! { + bench_peekable_sum, + bench_peekable_ref_sum, + (0i64..1000000).peekable() +} + +bench_sums! { + bench_peekable_chain_sum, + bench_peekable_chain_ref_sum, + (0i64..1000000).chain(0..1000000).peekable() +} + +bench_sums! { + bench_skip_sum, + bench_skip_ref_sum, + (0i64..1000000).skip(1000) +} + +bench_sums! { + bench_skip_chain_sum, + bench_skip_chain_ref_sum, + (0i64..1000000).chain(0..1000000).skip(1000) +} + +bench_sums! { + bench_skip_while_sum, + bench_skip_while_ref_sum, + (0i64..1000000).skip_while(|&x| x < 1000) +} + +bench_sums! { + bench_skip_while_chain_sum, + bench_skip_while_chain_ref_sum, + (0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000) } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6f86f8caad0..e012cbd76ff 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -456,7 +456,7 @@ pub trait Ord: Eq + PartialOrd<Self> { /// assert_eq!(2, 1.max(2)); /// assert_eq!(2, 2.max(2)); /// ``` - #[stable(feature = "ord_max_min", since = "1.22.0")] + #[stable(feature = "ord_max_min", since = "1.21.0")] fn max(self, other: Self) -> Self where Self: Sized { if other >= self { other } else { self } @@ -472,7 +472,7 @@ pub trait Ord: Eq + PartialOrd<Self> { /// assert_eq!(1, 1.min(2)); /// assert_eq!(2, 2.min(2)); /// ``` - #[stable(feature = "ord_max_min", since = "1.22.0")] + #[stable(feature = "ord_max_min", since = "1.21.0")] fn min(self, other: Self) -> Self where Self: Sized { if self <= other { self } else { other } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 6f3c3863fae..e815d72d366 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -48,8 +48,25 @@ #![stable(feature = "rust1", since = "1.0.0")] -use str::FromStr; +use fmt; +/// A type used as the error type for implementations of fallible conversion +/// traits in cases where conversions cannot actually fail. +/// +/// Because `Infallible` has no variants, a value of this type can never exist. +/// It is used only to satisfy trait signatures that expect an error type, and +/// signals to both the compiler and the user that the error case is impossible. +#[unstable(feature = "try_from", issue = "33417")] +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum Infallible {} + +#[unstable(feature = "try_from", issue = "33417")] +impl fmt::Display for Infallible { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + match *self { + } + } +} /// A cheap reference-to-reference conversion. Used to convert a value to a /// reference value within generic code. /// @@ -417,6 +434,17 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T> } } +// Infallible conversions are semantically equivalent to fallible conversions +// with an uninhabited error type. +#[unstable(feature = "try_from", issue = "33417")] +impl<T, U> TryFrom<U> for T where T: From<U> { + type Error = Infallible; + + fn try_from(value: U) -> Result<Self, Self::Error> { + Ok(T::from(value)) + } +} + //////////////////////////////////////////////////////////////////////////////// // CONCRETE IMPLS //////////////////////////////////////////////////////////////////////////////// @@ -442,14 +470,3 @@ impl AsRef<str> for str { self } } - -// FromStr implies TryFrom<&str> -#[unstable(feature = "try_from", issue = "33417")] -impl<'a, T> TryFrom<&'a str> for T where T: FromStr -{ - type Error = <T as FromStr>::Err; - - fn try_from(s: &'a str) -> Result<T, Self::Error> { - FromStr::from_str(s) - } -} diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index cf6262bda97..6c251b9eb09 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -488,13 +488,14 @@ impl<'a> Display for Arguments<'a> { /// The origin is: Point { x: 0, y: 0 } /// ``` /// -/// There are a number of `debug_*` methods on `Formatter` to help you with manual +/// There are a number of `debug_*` methods on [`Formatter`] to help you with manual /// implementations, such as [`debug_struct`][debug_struct]. /// /// `Debug` implementations using either `derive` or the debug builder API -/// on `Formatter` support pretty printing using the alternate flag: `{:#?}`. +/// on [`Formatter`] support pretty printing using the alternate flag: `{:#?}`. /// /// [debug_struct]: ../../std/fmt/struct.Formatter.html#method.debug_struct +/// [`Formatter`]: ../../std/fmt/struct.Formatter.html /// /// Pretty printing with `#?`: /// @@ -1321,8 +1322,11 @@ impl<'a> Formatter<'a> { self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 } - /// Creates a `DebugStruct` builder designed to assist with creation of - /// `fmt::Debug` implementations for structs. + /// Creates a [`DebugStruct`] builder designed to assist with creation of + /// [`fmt::Debug`] implementations for structs. + /// + /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.html + /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.html /// /// # Examples /// @@ -1700,8 +1704,18 @@ impl<T: ?Sized + Debug> Debug for RefCell<T> { .finish() } Err(_) => { + // The RefCell is mutably borrowed so we can't look at its value + // here. Show a placeholder instead. + struct BorrowedPlaceholder; + + impl Debug for BorrowedPlaceholder { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_str("<borrowed>") + } + } + f.debug_struct("RefCell") - .field("value", &"<borrowed>") + .field("value", &BorrowedPlaceholder) .finish() } } diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index 9a7914064fd..cb215a38e53 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -68,3 +68,22 @@ macro_rules! forward_ref_binop { } } } + +// implements "T op= &U", based on "T op= U" +// where U is expected to be `Copy`able +macro_rules! forward_ref_op_assign { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_op_assign!(impl $imp, $method for $t, $u, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + impl<'a> $imp<&'a $u> for $t { + #[inline] + fn $method(&mut self, other: &'a $u) { + $imp::$method(self, *other); + } + } + } +} + diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index edafd0ce2c2..e9e31065cf8 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -518,7 +518,7 @@ pub trait Iterator { /// .for_each(|(i, x)| println!("{}:{}", i, x)); /// ``` #[inline] - #[stable(feature = "iterator_for_each", since = "1.22.0")] + #[stable(feature = "iterator_for_each", since = "1.21.0")] fn for_each<F>(self, mut f: F) where Self: Sized, F: FnMut(Self::Item), { @@ -1337,7 +1337,7 @@ pub trait Iterator { (left, right) } - /// An iterator adaptor that applies a function, producing a single, final value. + /// An iterator method that applies a function, producing a single, final value. /// /// `fold()` takes two arguments: an initial value, and a closure with two /// arguments: an 'accumulator', and an element. The closure returns the value that diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index a596ffd6ae8..8d2521b053e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -359,6 +359,12 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, f) + } + #[inline] fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool @@ -379,6 +385,12 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() } + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, f) + } + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool { @@ -449,6 +461,12 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> fn next_back(&mut self) -> Option<T> { self.it.next_back().cloned() } + + fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.rfold(init, move |acc, elt| f(acc, elt.clone())) + } } #[stable(feature = "iter_cloned", since = "1.1.0")] @@ -470,7 +488,7 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I> {} #[doc(hidden)] -unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> +default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess<Item=&'a T>, T: Clone { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { @@ -481,6 +499,18 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> fn may_have_side_effect() -> bool { true } } +#[doc(hidden)] +unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> + where I: TrustedRandomAccess<Item=&'a T>, T: Copy +{ + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + *self.it.get_unchecked(i) + } + + #[inline] + fn may_have_side_effect() -> bool { false } +} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I> where I: TrustedLen<Item=&'a T>, @@ -528,7 +558,7 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator { #[unstable(feature = "fused", issue = "35602")] impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {} -/// An adapter for stepping iterators by a custom amount. +/// An iterator for stepping iterators by a custom amount. /// /// This `struct` is created by the [`step_by`] method on [`Iterator`]. See /// its documentation for more. @@ -761,6 +791,26 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where ChainState::Back => self.b.next_back(), } } + + fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.rfold(accum, &mut f); + } + _ => { } + } + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.rfold(accum, &mut f); + } + _ => { } + } + accum + } + } // Note: *both* must be fused to handle double-ended iterators. @@ -1094,6 +1144,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where fn next_back(&mut self) -> Option<B> { self.iter.next_back().map(&mut self.f) } + + fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.rfold(init, move |acc, elt| g(acc, f(elt))) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1193,6 +1250,18 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool } count } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut predicate = self.predicate; + self.iter.fold(init, move |acc, item| if predicate(&item) { + fold(acc, item) + } else { + acc + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1208,6 +1277,18 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> } None } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut predicate = self.predicate; + self.iter.rfold(init, move |acc, item| if predicate(&item) { + fold(acc, item) + } else { + acc + }) + } } #[unstable(feature = "fused", issue = "35602")] @@ -1259,6 +1340,17 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1274,6 +1366,17 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> } None } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.rfold(init, move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + }) + } } #[unstable(feature = "fused", issue = "35602")] @@ -1338,6 +1441,19 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { fn count(self) -> usize { self.iter.count() } + + #[inline] + #[rustc_inherit_overflow_checks] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut count = self.count; + self.iter.fold(init, move |acc, item| { + let acc = fold(acc, (count, item)); + count += 1; + acc + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1353,6 +1469,19 @@ impl<I> DoubleEndedIterator for Enumerate<I> where (self.count + len, a) }) } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + // Can safely add and subtract the count, as `ExactSizeIterator` promises + // that the number of elements fits into a `usize`. + let mut count = self.count + self.iter.len(); + self.iter.rfold(init, move |acc, item| { + count -= 1; + fold(acc, (count, item)) + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1464,6 +1593,18 @@ impl<I: Iterator> Iterator for Peekable<I> { let hi = hi.and_then(|x| x.checked_add(peek_len)); (lo, hi) } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let acc = match self.peeked { + Some(None) => return init, + Some(Some(v)) => fold(init, v), + None => init, + }; + self.iter.fold(acc, fold) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1572,6 +1713,19 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P> let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + #[inline] + fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if !self.flag { + match self.next() { + Some(v) => init = fold(init, v), + None => return init, + } + } + self.iter.fold(init, fold) + } } #[unstable(feature = "fused", issue = "35602")] @@ -1712,6 +1866,19 @@ impl<I> Iterator for Skip<I> where I: Iterator { (lower, upper) } + + #[inline] + fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.n > 0 { + // nth(n) skips n+1 + if self.iter.nth(self.n - 1).is_none() { + return init; + } + } + self.iter.fold(init, fold) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1934,6 +2101,16 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher } } } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.frontiter.into_iter() + .chain(self.iter.map(self.f).map(U::into_iter)) + .chain(self.backiter) + .rfold(init, |acc, iter| iter.rfold(acc, &mut fold)) + } } #[unstable(feature = "fused", issue = "35602")] @@ -2011,6 +2188,17 @@ impl<I> Iterator for Fuse<I> where I: Iterator { self.iter.size_hint() } } + + #[inline] + default fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.done { + init + } else { + self.iter.fold(init, fold) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2025,6 +2213,17 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator { next } } + + #[inline] + default fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.done { + init + } else { + self.iter.rfold(init, fold) + } + } } unsafe impl<I> TrustedRandomAccess for Fuse<I> @@ -2065,6 +2264,13 @@ impl<I> Iterator for Fuse<I> where I: FusedIterator { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, fold) + } } #[unstable(feature = "fused", reason = "recently added", issue = "35602")] @@ -2075,6 +2281,13 @@ impl<I> DoubleEndedIterator for Fuse<I> fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, fold) + } } @@ -2139,6 +2352,14 @@ impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2150,6 +2371,14 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F> let next = self.iter.next_back(); self.do_inspect(next) } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 73d518b570a..e9aee4a4676 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -89,6 +89,7 @@ macro_rules! step_impl_unsigned { } #[inline] + #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option<Self> { match <$t>::try_from(n) { Ok(n_as_t) => self.checked_add(n_as_t), @@ -120,6 +121,7 @@ macro_rules! step_impl_signed { } #[inline] + #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option<Self> { match <$unsigned>::try_from(n) { Ok(n_as_unsigned) => { diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 7ef50396c82..28236d193c3 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -415,6 +415,70 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option<Self::Item>; + /// An iterator method that reduces the iterator's elements to a single, + /// final value, starting from the back. + /// + /// This is the reverse version of [`fold()`]: it takes elements starting from + /// the back of the iterator. + /// + /// `rfold()` takes two arguments: an initial value, and a closure with two + /// arguments: an 'accumulator', and an element. The closure returns the value that + /// the accumulator should have for the next iteration. + /// + /// The initial value is the value the accumulator will have on the first + /// call. + /// + /// After applying this closure to every element of the iterator, `rfold()` + /// returns the accumulator. + /// + /// This operation is sometimes called 'reduce' or 'inject'. + /// + /// Folding is useful whenever you have a collection of something, and want + /// to produce a single value from it. + /// + /// [`fold()`]: trait.Iterator.html#method.fold + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_rfold)] + /// let a = [1, 2, 3]; + /// + /// // the sum of all of the elements of a + /// let sum = a.iter() + /// .rfold(0, |acc, &x| acc + x); + /// + /// assert_eq!(sum, 6); + /// ``` + /// + /// This example builds a string, starting with an initial value + /// and continuing with each element from the back until the front: + /// + /// ``` + /// #![feature(iter_rfold)] + /// let numbers = [1, 2, 3, 4, 5]; + /// + /// let zero = "0".to_string(); + /// + /// let result = numbers.iter().rfold(zero, |acc, &x| { + /// format!("({} + {})", x, acc) + /// }); + /// + /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))"); + /// ``` + #[inline] + #[unstable(feature = "iter_rfold", issue = "44705")] + fn rfold<B, F>(mut self, mut accum: B, mut f: F) -> B where + Self: Sized, F: FnMut(B, Self::Item) -> B, + { + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + /// Searches for an element of an iterator from the right that satisfies a predicate. /// /// `rfind()` takes a closure that returns `true` or `false`. It applies diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index e8fd729b638..f56a9a40332 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -122,7 +122,7 @@ pub trait Sized { /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "unsize", issue = "27732")] -#[lang="unsize"] +#[lang = "unsize"] pub trait Unsize<T: ?Sized> { // Empty. } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 34994dc3b70..c869054cee8 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -177,15 +177,59 @@ pub fn forget<T>(t: T) { /// Returns the size of a type in bytes. /// -/// More specifically, this is the offset in bytes between successive -/// items of the same type, including alignment padding. +/// More specifically, this is the offset in bytes between successive elements +/// in an array with that item type including alignment padding. Thus, for any +/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`. +/// +/// In general, the size of a type is not stable across compilations, but +/// specific types such as primitives are. +/// +/// The following table gives the size for primitives. +/// +/// Type | size_of::\<Type>() +/// ---- | --------------- +/// () | 0 +/// u8 | 1 +/// u16 | 2 +/// u32 | 4 +/// u64 | 8 +/// i8 | 1 +/// i16 | 2 +/// i32 | 4 +/// i64 | 8 +/// f32 | 4 +/// f64 | 8 +/// char | 4 +/// +/// Furthermore, `usize` and `isize` have the same size. +/// +/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have +/// the same size. If `T` is Sized, all of those types have the same size as `usize`. +/// +/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` +/// have the same size. Likewise for `*const T` and `*mut T`. /// /// # Examples /// /// ``` /// use std::mem; /// +/// // Some primitives /// assert_eq!(4, mem::size_of::<i32>()); +/// assert_eq!(8, mem::size_of::<f64>()); +/// assert_eq!(0, mem::size_of::<()>()); +/// +/// // Some arrays +/// assert_eq!(8, mem::size_of::<[i32; 2]>()); +/// assert_eq!(12, mem::size_of::<[i32; 3]>()); +/// assert_eq!(0, mem::size_of::<[i32; 0]>()); +/// +/// +/// // Pointer size equality +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>()); +/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -358,7 +402,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize { /// } /// ``` #[inline] -#[stable(feature = "needs_drop", since = "1.22.0")] +#[stable(feature = "needs_drop", since = "1.21.0")] pub fn needs_drop<T>() -> bool { unsafe { intrinsics::needs_drop::<T>() } } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index bf31deae7a6..85be8a08728 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -12,7 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use convert::TryFrom; +use convert::{Infallible, TryFrom}; use fmt; use intrinsics; use str::FromStr; @@ -2507,16 +2507,24 @@ impl fmt::Display for TryFromIntError { } } +#[unstable(feature = "try_from", issue = "33417")] +impl From<Infallible> for TryFromIntError { + fn from(infallible: Infallible) -> TryFromIntError { + match infallible { + } + } +} + // no possible bounds violation macro_rules! try_from_unbounded { ($source:ty, $($target:ty),*) => {$( #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { - type Error = TryFromIntError; + type Error = Infallible; #[inline] - fn try_from(u: $source) -> Result<$target, TryFromIntError> { - Ok(u as $target) + fn try_from(value: $source) -> Result<Self, Self::Error> { + Ok(value as $target) } } )*} @@ -2588,31 +2596,17 @@ macro_rules! rev { } /// intra-sign conversions -try_from_unbounded!(u8, u8, u16, u32, u64, u128); -try_from_unbounded!(u16, u16, u32, u64, u128); -try_from_unbounded!(u32, u32, u64, u128); -try_from_unbounded!(u64, u64, u128); -try_from_unbounded!(u128, u128); try_from_upper_bounded!(u16, u8); try_from_upper_bounded!(u32, u16, u8); try_from_upper_bounded!(u64, u32, u16, u8); try_from_upper_bounded!(u128, u64, u32, u16, u8); -try_from_unbounded!(i8, i8, i16, i32, i64, i128); -try_from_unbounded!(i16, i16, i32, i64, i128); -try_from_unbounded!(i32, i32, i64, i128); -try_from_unbounded!(i64, i64, i128); -try_from_unbounded!(i128, i128); try_from_both_bounded!(i16, i8); try_from_both_bounded!(i32, i16, i8); try_from_both_bounded!(i64, i32, i16, i8); try_from_both_bounded!(i128, i64, i32, i16, i8); // unsigned-to-signed -try_from_unbounded!(u8, i16, i32, i64, i128); -try_from_unbounded!(u16, i32, i64, i128); -try_from_unbounded!(u32, i64, i128); -try_from_unbounded!(u64, i128); try_from_upper_bounded!(u8, i8); try_from_upper_bounded!(u16, i8, i16); try_from_upper_bounded!(u32, i8, i16, i32); @@ -2631,15 +2625,13 @@ try_from_both_bounded!(i64, u32, u16, u8); try_from_both_bounded!(i128, u64, u32, u16, u8); // usize/isize -try_from_unbounded!(usize, usize); try_from_upper_bounded!(usize, isize); try_from_lower_bounded!(isize, usize); -try_from_unbounded!(isize, isize); #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::TryFrom; + use convert::{Infallible, TryFrom}; try_from_upper_bounded!(usize, u8); try_from_unbounded!(usize, u16, u32, u64, u128); @@ -2651,21 +2643,21 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8); try_from_unbounded!(isize, i16, i32, i64, i128); - rev!(try_from_unbounded, usize, u8, u16); + rev!(try_from_unbounded, usize, u16); rev!(try_from_upper_bounded, usize, u32, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16); rev!(try_from_both_bounded, usize, i32, i64, i128); rev!(try_from_unbounded, isize, u8); rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); - rev!(try_from_unbounded, isize, i8, i16); + rev!(try_from_unbounded, isize, i16); rev!(try_from_both_bounded, isize, i32, i64, i128); } #[cfg(target_pointer_width = "32")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::TryFrom; + use convert::{Infallible, TryFrom}; try_from_upper_bounded!(usize, u8, u16); try_from_unbounded!(usize, u32, u64, u128); @@ -2677,21 +2669,21 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16); try_from_unbounded!(isize, i32, i64, i128); - rev!(try_from_unbounded, usize, u8, u16, u32); + rev!(try_from_unbounded, usize, u16, u32); rev!(try_from_upper_bounded, usize, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32); rev!(try_from_both_bounded, usize, i64, i128); rev!(try_from_unbounded, isize, u8, u16); rev!(try_from_upper_bounded, isize, u32, u64, u128); - rev!(try_from_unbounded, isize, i8, i16, i32); + rev!(try_from_unbounded, isize, i16, i32); rev!(try_from_both_bounded, isize, i64, i128); } #[cfg(target_pointer_width = "64")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::TryFrom; + use convert::{Infallible, TryFrom}; try_from_upper_bounded!(usize, u8, u16, u32); try_from_unbounded!(usize, u64, u128); @@ -2703,14 +2695,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16, i32); try_from_unbounded!(isize, i64, i128); - rev!(try_from_unbounded, usize, u8, u16, u32, u64); + rev!(try_from_unbounded, usize, u16, u32, u64); rev!(try_from_upper_bounded, usize, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); rev!(try_from_both_bounded, usize, i128); rev!(try_from_unbounded, isize, u8, u16, u32); rev!(try_from_upper_bounded, isize, u64, u128); - rev!(try_from_unbounded, isize, i8, i16, i32, i64); + rev!(try_from_unbounded, isize, i16, i32, i64); rev!(try_from_both_bounded, isize, i128); } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index acdf685e850..ae1b0b3ce11 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -36,6 +36,7 @@ macro_rules! sh_impl_signed { *self = *self << other; } } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] impl Shr<$f> for Wrapping<$t> { @@ -58,6 +59,7 @@ macro_rules! sh_impl_signed { *self = *self >> other; } } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } ) } @@ -80,6 +82,7 @@ macro_rules! sh_impl_unsigned { *self = *self << other; } } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] impl Shr<$f> for Wrapping<$t> { @@ -98,6 +101,7 @@ macro_rules! sh_impl_unsigned { *self = *self >> other; } } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } ) } @@ -142,6 +146,7 @@ macro_rules! wrapping_impl { *self = *self + other; } } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl Sub for Wrapping<$t> { @@ -162,6 +167,7 @@ macro_rules! wrapping_impl { *self = *self - other; } } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl Mul for Wrapping<$t> { @@ -182,6 +188,7 @@ macro_rules! wrapping_impl { *self = *self * other; } } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_div", since = "1.3.0")] impl Div for Wrapping<$t> { @@ -202,6 +209,7 @@ macro_rules! wrapping_impl { *self = *self / other; } } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_impls", since = "1.7.0")] impl Rem for Wrapping<$t> { @@ -222,6 +230,7 @@ macro_rules! wrapping_impl { *self = *self % other; } } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl Not for Wrapping<$t> { @@ -254,6 +263,7 @@ macro_rules! wrapping_impl { *self = *self ^ other; } } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl BitOr for Wrapping<$t> { @@ -274,6 +284,7 @@ macro_rules! wrapping_impl { *self = *self | other; } } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl BitAnd for Wrapping<$t> { @@ -294,6 +305,7 @@ macro_rules! wrapping_impl { *self = *self & other; } } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_neg", since = "1.10.0")] impl Neg for Wrapping<$t> { diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 62007caedd3..8b3d662a6db 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -662,6 +662,8 @@ macro_rules! add_assign_impl { #[rustc_inherit_overflow_checks] fn add_assign(&mut self, other: $t) { *self += other } } + + forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t } )+) } @@ -713,6 +715,8 @@ macro_rules! sub_assign_impl { #[rustc_inherit_overflow_checks] fn sub_assign(&mut self, other: $t) { *self -= other } } + + forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t } )+) } @@ -755,6 +759,8 @@ macro_rules! mul_assign_impl { #[rustc_inherit_overflow_checks] fn mul_assign(&mut self, other: $t) { *self *= other } } + + forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t } )+) } @@ -796,6 +802,8 @@ macro_rules! div_assign_impl { #[inline] fn div_assign(&mut self, other: $t) { *self /= other } } + + forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t } )+) } @@ -841,6 +849,8 @@ macro_rules! rem_assign_impl { #[inline] fn rem_assign(&mut self, other: $t) { *self %= other } } + + forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t } )+) } diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index 0bc5e554cb3..7ac5fc4debf 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -593,6 +593,8 @@ macro_rules! bitand_assign_impl { #[inline] fn bitand_assign(&mut self, other: $t) { *self &= other } } + + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t } )+) } @@ -638,6 +640,8 @@ macro_rules! bitor_assign_impl { #[inline] fn bitor_assign(&mut self, other: $t) { *self |= other } } + + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t } )+) } @@ -683,6 +687,8 @@ macro_rules! bitxor_assign_impl { #[inline] fn bitxor_assign(&mut self, other: $t) { *self ^= other } } + + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t } )+) } @@ -729,6 +735,8 @@ macro_rules! shl_assign_impl { *self <<= other } } + + forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } ) } @@ -793,6 +801,8 @@ macro_rules! shr_assign_impl { *self >>= other } } + + forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } ) } diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 463a50491a8..3f573f7c7eb 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -241,9 +241,9 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> { } } -/// An range bounded inclusively below and above (`start...end`). +/// An range bounded inclusively below and above (`start..=end`). /// -/// The `RangeInclusive` `start...end` contains all values with `x >= start` +/// The `RangeInclusive` `start..=end` contains all values with `x >= start` /// and `x <= end`. /// /// # Examples @@ -251,12 +251,12 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> { /// ``` /// #![feature(inclusive_range,inclusive_range_syntax)] /// -/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 }); -/// assert_eq!(3 + 4 + 5, (3...5).sum()); +/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 }); +/// assert_eq!(3 + 4 + 5, (3..=5).sum()); /// /// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); -/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive +/// assert_eq!(arr[ ..=2], [0,1,2 ]); +/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive /// ``` #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] @@ -276,7 +276,7 @@ pub struct RangeInclusive<Idx> { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}...{:?}", self.start, self.end) + write!(fmt, "{:?}..={:?}", self.start, self.end) } } @@ -289,32 +289,32 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// ``` /// #![feature(range_contains,inclusive_range_syntax)] /// - /// assert!(!(3...5).contains(2)); - /// assert!( (3...5).contains(3)); - /// assert!( (3...5).contains(4)); - /// assert!( (3...5).contains(5)); - /// assert!(!(3...5).contains(6)); + /// assert!(!(3..=5).contains(2)); + /// assert!( (3..=5).contains(3)); + /// assert!( (3..=5).contains(4)); + /// assert!( (3..=5).contains(5)); + /// assert!(!(3..=5).contains(6)); /// - /// assert!( (3...3).contains(3)); - /// assert!(!(3...2).contains(3)); + /// assert!( (3..=3).contains(3)); + /// assert!(!(3..=2).contains(3)); /// ``` pub fn contains(&self, item: Idx) -> bool { self.start <= item && item <= self.end } } -/// A range only bounded inclusively above (`...end`). +/// A range only bounded inclusively above (`..=end`). /// -/// The `RangeToInclusive` `...end` contains all values with `x <= end`. +/// The `RangeToInclusive` `..=end` contains all values with `x <= end`. /// It cannot serve as an [`Iterator`] because it doesn't have a starting point. /// /// # Examples /// -/// The `...end` syntax is a `RangeToInclusive`: +/// The `..=end` syntax is a `RangeToInclusive`: /// /// ``` /// #![feature(inclusive_range,inclusive_range_syntax)] -/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); +/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 }); /// ``` /// /// It does not have an [`IntoIterator`] implementation, so you can't use it in a @@ -325,7 +325,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// /// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>: /// // std::iter::Iterator` is not satisfied -/// for i in ...5 { +/// for i in ..=5 { /// // ... /// } /// ``` @@ -337,8 +337,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// #![feature(inclusive_range_syntax)] /// /// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive -/// assert_eq!(arr[1...2], [ 1,2 ]); +/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive +/// assert_eq!(arr[1..=2], [ 1,2 ]); /// ``` /// /// [`IntoIterator`]: ../iter/trait.Iterator.html @@ -357,7 +357,7 @@ pub struct RangeToInclusive<Idx> { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "...{:?}", self.end) + write!(fmt, "..={:?}", self.end) } } @@ -370,9 +370,9 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> { /// ``` /// #![feature(range_contains,inclusive_range_syntax)] /// - /// assert!( (...5).contains(-1_000_000_000)); - /// assert!( (...5).contains(5)); - /// assert!(!(...5).contains(6)); + /// assert!( (..=5).contains(-1_000_000_000)); + /// assert!( (..=5).contains(5)); + /// assert!(!(..=5).contains(6)); /// ``` pub fn contains(&self, item: Idx) -> bool { (item <= self.end) diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index 58da290cfb6..cd896859b16 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -42,7 +42,7 @@ use marker::Unsize; /// [unsize]: ../marker/trait.Unsize.html /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "27732")] -#[lang="coerce_unsized"] +#[lang = "coerce_unsized"] pub trait CoerceUnsized<T> { // Empty. } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 138e04c7737..980ea551f08 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -146,7 +146,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use iter::{FromIterator, FusedIterator, TrustedLen}; -use mem; +use {mem, ops}; // Note that this is not a lang item per se, but it has a hidden dependency on // `Iterator`, which is one. The compiler assumes that the `next` method of @@ -1123,3 +1123,29 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { } } } + +/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish +/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can +/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that +/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result. +#[unstable(feature = "try_trait", issue = "42327")] +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +pub struct NoneError; + +#[unstable(feature = "try_trait", issue = "42327")] +impl<T> ops::Try for Option<T> { + type Ok = T; + type Error = NoneError; + + fn into_result(self) -> Result<T, NoneError> { + self.ok_or(NoneError) + } + + fn from_ok(v: T) -> Self { + Some(v) + } + + fn from_error(_: NoneError) -> Self { + None + } +} diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 4041a3760e5..34d31044653 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -56,7 +56,7 @@ pub use intrinsics::write_bytes; /// This has all the same safety problems as `ptr::read` with respect to /// invalid pointers, types, and double drops. #[stable(feature = "drop_in_place", since = "1.8.0")] -#[lang="drop_in_place"] +#[lang = "drop_in_place"] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { // Code here does not matter - this is replaced by the diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index dacc014955a..ae243f3f246 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -16,6 +16,9 @@ #![stable(feature = "rust1", since = "1.0.0")] +// FIXME: after next stage0, change RangeInclusive { ... } back to ..= +use ops::RangeInclusive; + // How this module is organized. // // The library infrastructure for slices is fairly messy. There's @@ -1044,32 +1047,32 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { #[inline] fn get(self, slice: &[T]) -> Option<&[T]> { - (0...self.end).get(slice) + (RangeInclusive { start: 0, end: self.end }).get(slice) } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { - (0...self.end).get_mut(slice) + (RangeInclusive { start: 0, end: self.end }).get_mut(slice) } #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (0...self.end).get_unchecked(slice) + (RangeInclusive { start: 0, end: self.end }).get_unchecked(slice) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (0...self.end).get_unchecked_mut(slice) + (RangeInclusive { start: 0, end: self.end }).get_unchecked_mut(slice) } #[inline] fn index(self, slice: &[T]) -> &[T] { - (0...self.end).index(slice) + (RangeInclusive { start: 0, end: self.end }).index(slice) } #[inline] fn index_mut(self, slice: &mut [T]) -> &mut [T] { - (0...self.end).index_mut(slice) + (RangeInclusive { start: 0, end: self.end }).index_mut(slice) } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index c24cdb30bad..0af9fcf0a3d 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -18,9 +18,9 @@ use self::pattern::Pattern; use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use char; -use convert::TryFrom; use fmt; -use iter::{Map, Cloned, FusedIterator}; +use iter::{Map, Cloned, FusedIterator, TrustedLen}; +use iter_private::TrustedRandomAccess; use slice::{self, SliceIndex}; use mem; @@ -818,6 +818,17 @@ impl<'a> ExactSizeIterator for Bytes<'a> { #[unstable(feature = "fused", issue = "35602")] impl<'a> FusedIterator for Bytes<'a> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a> TrustedLen for Bytes<'a> {} + +#[doc(hidden)] +unsafe impl<'a> TrustedRandomAccess for Bytes<'a> { + unsafe fn get_unchecked(&mut self, i: usize) -> u8 { + self.0.get_unchecked(i) + } + fn may_have_side_effect() -> bool { false } +} + /// This macro generates a Clone impl for string pattern API /// wrapper types of the form X<'a, P> macro_rules! derive_pattern_clone { @@ -1399,9 +1410,6 @@ Section: Comparing strings */ /// Bytewise slice equality -/// NOTE: This function is (ab)used in rustc::middle::trans::_match -/// to compare &[u8] byte slices that are not necessarily valid UTF-8. -#[lang = "str_eq"] #[inline] fn eq_slice(a: &str, b: &str) -> bool { a.as_bytes() == b.as_bytes() @@ -2189,7 +2197,7 @@ pub trait StrExt { #[stable(feature = "core", since = "1.6.0")] fn is_empty(&self) -> bool; #[stable(feature = "core", since = "1.6.0")] - fn parse<'a, T: TryFrom<&'a str>>(&'a self) -> Result<T, T::Error>; + fn parse<T: FromStr>(&self) -> Result<T, T::Err>; } // truncate `&str` to length at most equal to `max` @@ -2509,9 +2517,7 @@ impl StrExt for str { fn is_empty(&self) -> bool { self.len() == 0 } #[inline] - fn parse<'a, T>(&'a self) -> Result<T, T::Error> where T: TryFrom<&'a str> { - T::try_from(self) - } + fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 3dd08e69710..465d31b5f49 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -926,10 +926,24 @@ macro_rules! atomic_int { $stable_cxchg:meta, $stable_debug:meta, $stable_access:meta, + $s_int_type:expr, $int_ref:expr, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. /// - /// This type has the same in-memory representation as the underlying integer type. + /// This type has the same in-memory representation as the underlying + /// integer type, [` + #[doc = $s_int_type] + /// `]( + #[doc = $int_ref] + /// ). For more about the differences between atomic types and + /// non-atomic types, please see the [module-level documentation]. + /// + /// Please note that examples are shared between atomic variants of + /// primitive integer types, so it's normal that they are all + /// demonstrating [`AtomicIsize`]. + /// + /// [module-level documentation]: index.html + /// [`AtomicIsize`]: struct.AtomicIsize.html #[$stable] pub struct $atomic_type { v: UnsafeCell<$int_type>, @@ -1339,6 +1353,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i8", "../../../std/primitive.i8.html", i8 AtomicI8 ATOMIC_I8_INIT } #[cfg(target_has_atomic = "8")] @@ -1348,6 +1363,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u8", "../../../std/primitive.u8.html", u8 AtomicU8 ATOMIC_U8_INIT } #[cfg(target_has_atomic = "16")] @@ -1357,6 +1373,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i16", "../../../std/primitive.i16.html", i16 AtomicI16 ATOMIC_I16_INIT } #[cfg(target_has_atomic = "16")] @@ -1366,6 +1383,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u16", "../../../std/primitive.u16.html", u16 AtomicU16 ATOMIC_U16_INIT } #[cfg(target_has_atomic = "32")] @@ -1375,6 +1393,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i32", "../../../std/primitive.i32.html", i32 AtomicI32 ATOMIC_I32_INIT } #[cfg(target_has_atomic = "32")] @@ -1384,6 +1403,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u32", "../../../std/primitive.u32.html", u32 AtomicU32 ATOMIC_U32_INIT } #[cfg(target_has_atomic = "64")] @@ -1393,6 +1413,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "i64", "../../../std/primitive.i64.html", i64 AtomicI64 ATOMIC_I64_INIT } #[cfg(target_has_atomic = "64")] @@ -1402,6 +1423,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + "u64", "../../../std/primitive.u64.html", u64 AtomicU64 ATOMIC_U64_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1411,6 +1433,7 @@ atomic_int!{ stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), + "isize", "../../../std/primitive.isize.html", isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1420,6 +1443,7 @@ atomic_int!{ stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), + "usize", "../../../std/primitive.usize.html", usize AtomicUsize ATOMIC_USIZE_INIT } @@ -1752,7 +1776,7 @@ pub fn fence(order: Ordering) { /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [memory barriers]: https://www.kernel.org/doc/Documentation/memory-barriers.txt #[inline] -#[stable(feature = "compiler_fences", since = "1.22.0")] +#[stable(feature = "compiler_fences", since = "1.21.0")] pub fn compiler_fence(order: Ordering) { unsafe { match order { diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index 7c3b90c8153..4e10ceac878 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -32,7 +32,6 @@ fn test_convert() { #[test] fn test_from_str() { assert_eq!(char::from_str("a").unwrap(), 'a'); - assert_eq!(char::try_from("a").unwrap(), 'a'); assert_eq!(char::from_str("\0").unwrap(), '\0'); assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}'); assert!(char::from_str("").is_err()); diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 59ae30de452..f8c6fc5c8fa 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -249,6 +249,25 @@ fn test_filter_map() { } #[test] +fn test_filter_map_fold() { + let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let ys = [0*0, 2*2, 4*4, 6*6, 8*8]; + let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None }); + let i = it.fold(0, |i, x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None }); + let i = it.rfold(ys.len(), |i, x| { + assert_eq!(x, ys[i - 1]); + i - 1 + }); + assert_eq!(i, 0); +} + +#[test] fn test_iterator_enumerate() { let xs = [0, 1, 2, 3, 4, 5]; let it = xs.iter().enumerate(); @@ -282,7 +301,31 @@ fn test_iterator_enumerate_nth() { #[test] fn test_iterator_enumerate_count() { let xs = [0, 1, 2, 3, 4, 5]; - assert_eq!(xs.iter().count(), 6); + assert_eq!(xs.iter().enumerate().count(), 6); +} + +#[test] +fn test_iterator_enumerate_fold() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + // steal a couple to get an interesting offset + assert_eq!(it.next(), Some((0, &0))); + assert_eq!(it.next(), Some((1, &1))); + let i = it.fold(2, |i, (j, &x)| { + assert_eq!(i, j); + assert_eq!(x, xs[j]); + i + 1 + }); + assert_eq!(i, xs.len()); + + let mut it = xs.iter().enumerate(); + assert_eq!(it.next(), Some((0, &0))); + let i = it.rfold(xs.len() - 1, |i, (j, &x)| { + assert_eq!(i, j); + assert_eq!(x, xs[j]); + i - 1 + }); + assert_eq!(i, 0); } #[test] @@ -292,6 +335,25 @@ fn test_iterator_filter_count() { } #[test] +fn test_iterator_filter_fold() { + let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let ys = [0, 2, 4, 6, 8]; + let it = xs.iter().filter(|&&x| x % 2 == 0); + let i = it.fold(0, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let it = xs.iter().filter(|&&x| x % 2 == 0); + let i = it.rfold(ys.len(), |i, &x| { + assert_eq!(x, ys[i - 1]); + i - 1 + }); + assert_eq!(i, 0); +} + +#[test] fn test_iterator_peekable() { let xs = vec![0, 1, 2, 3, 4, 5]; let mut it = xs.iter().cloned().peekable(); @@ -381,6 +443,18 @@ fn test_iterator_peekable_last() { assert_eq!(it.last(), None); } +#[test] +fn test_iterator_peekable_fold() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().peekable(); + assert_eq!(it.peek(), Some(&&0)); + let i = it.fold(0, |i, &x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); +} + /// This is an iterator that follows the Iterator contract, /// but it is not fused. After having returned None once, it will start /// producing elements if .next() is called again. @@ -471,6 +545,26 @@ fn test_iterator_skip_while() { } #[test] +fn test_iterator_skip_while_fold() { + let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let it = xs.iter().skip_while(|&x| *x < 15); + let i = it.fold(0, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let mut it = xs.iter().skip_while(|&x| *x < 15); + assert_eq!(it.next(), Some(&ys[0])); // process skips before folding + let i = it.fold(1, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); +} + +#[test] fn test_iterator_skip() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; let ys = [13, 15, 16, 17, 19, 20, 30]; @@ -567,6 +661,26 @@ fn test_iterator_skip_last() { } #[test] +fn test_iterator_skip_fold() { + let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let it = xs.iter().skip(5); + let i = it.fold(0, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); + + let mut it = xs.iter().skip(5); + assert_eq!(it.next(), Some(&ys[0])); // process skips before folding + let i = it.fold(1, |i, &x| { + assert_eq!(x, ys[i]); + i + 1 + }); + assert_eq!(i, ys.len()); +} + +#[test] fn test_iterator_take() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; let ys = [0, 1, 2, 3, 5]; @@ -661,13 +775,22 @@ fn test_iterator_flat_map_fold() { let xs = [0, 3, 6]; let ys = [1, 2, 3, 4, 5, 6, 7]; let mut it = xs.iter().flat_map(|&x| x..x+3); - it.next(); - it.next_back(); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.next_back(), Some(8)); let i = it.fold(0, |i, x| { assert_eq!(x, ys[i]); i + 1 }); assert_eq!(i, ys.len()); + + let mut it = xs.iter().flat_map(|&x| x..x+3); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.next_back(), Some(8)); + let i = it.rfold(ys.len(), |i, x| { + assert_eq!(x, ys[i - 1]); + i - 1 + }); + assert_eq!(i, 0); } #[test] @@ -685,6 +808,32 @@ fn test_inspect() { } #[test] +fn test_inspect_fold() { + let xs = [1, 2, 3, 4]; + let mut n = 0; + { + let it = xs.iter().inspect(|_| n += 1); + let i = it.fold(0, |i, &x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); + } + assert_eq!(n, xs.len()); + + let mut n = 0; + { + let it = xs.iter().inspect(|_| n += 1); + let i = it.rfold(xs.len(), |i, &x| { + assert_eq!(x, xs[i - 1]); + i - 1 + }); + assert_eq!(i, 0); + } + assert_eq!(n, xs.len()); +} + +#[test] fn test_cycle() { let cycle_len = 3; let it = (0..).step_by(1).take(cycle_len).cycle(); @@ -1094,21 +1243,21 @@ fn test_range() { #[test] fn test_range_inclusive_exhaustion() { - let mut r = 10...10; + let mut r = 10..=10; assert_eq!(r.next(), Some(10)); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); - let mut r = 10...10; + let mut r = 10..=10; assert_eq!(r.next_back(), Some(10)); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); - let mut r = 10...12; + let mut r = 10..=12; assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); - let mut r = 10...12; + let mut r = 10..=12; assert_eq!(r.nth(5), None); - assert_eq!(r, 1...0); + assert_eq!(r, 1..=0); } @@ -1145,20 +1294,20 @@ fn test_range_from_nth() { #[test] fn test_range_inclusive_nth() { - assert_eq!((10...15).nth(0), Some(10)); - assert_eq!((10...15).nth(1), Some(11)); - assert_eq!((10...15).nth(5), Some(15)); - assert_eq!((10...15).nth(6), None); + assert_eq!((10..=15).nth(0), Some(10)); + assert_eq!((10..=15).nth(1), Some(11)); + assert_eq!((10..=15).nth(5), Some(15)); + assert_eq!((10..=15).nth(6), None); - let mut r = 10_u8...20; + let mut r = 10_u8..=20; assert_eq!(r.nth(2), Some(12)); - assert_eq!(r, 13...20); + assert_eq!(r, 13..=20); assert_eq!(r.nth(2), Some(15)); - assert_eq!(r, 16...20); + assert_eq!(r, 16..=20); assert_eq!(r.is_empty(), false); assert_eq!(r.nth(10), None); assert_eq!(r.is_empty(), true); - assert_eq!(r, 1...0); // We may not want to document/promise this detail + assert_eq!(r, 1..=0); // We may not want to document/promise this detail } #[test] @@ -1242,6 +1391,31 @@ fn test_fuse_count() { } #[test] +fn test_fuse_fold() { + let xs = [0, 1, 2]; + let it = xs.iter(); // `FusedIterator` + let i = it.fuse().fold(0, |i, &x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); + + let it = xs.iter(); // `FusedIterator` + let i = it.fuse().rfold(xs.len(), |i, &x| { + assert_eq!(x, xs[i - 1]); + i - 1 + }); + assert_eq!(i, 0); + + let it = xs.iter().scan((), |_, &x| Some(x)); // `!FusedIterator` + let i = it.fuse().fold(0, |i, x| { + assert_eq!(x, xs[i]); + i + 1 + }); + assert_eq!(i, xs.len()); +} + +#[test] fn test_once() { let mut it = once(42); assert_eq!(it.next(), Some(42)); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 47995597a0a..afc5de7b0ee 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -25,6 +25,7 @@ #![feature(inclusive_range)] #![feature(inclusive_range_syntax)] #![feature(iter_rfind)] +#![feature(iter_rfold)] #![feature(nonzero)] #![feature(rand)] #![feature(raw)] @@ -38,6 +39,7 @@ #![feature(test)] #![feature(trusted_len)] #![feature(try_from)] +#![feature(try_trait)] #![feature(unique)] #![feature(const_atomic_bool_new)] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 400d53ce51a..7eb5ff98857 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::convert::TryFrom; +use core::convert::{TryFrom, TryInto}; use core::cmp::PartialEq; use core::fmt::Debug; use core::marker::Copy; +use core::num::TryFromIntError; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::option::Option; use core::option::Option::{Some, None}; @@ -134,6 +135,13 @@ fn test_empty() { assert_eq!("".parse::<u8>().ok(), None); } +#[test] +fn test_infallible_try_from_int_error() { + let func = |x: i8| -> Result<i32, TryFromIntError> { Ok(x.try_into()?) }; + + assert!(func(0).is_ok()); +} + macro_rules! test_impl_from { ($fn_name: ident, $Small: ty, $Large: ty) => { #[test] diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index 6bac55575fb..22109e28edd 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -270,3 +270,30 @@ fn test_cloned() { assert_eq!(opt_ref_ref.clone().cloned(), Some(&val)); assert_eq!(opt_ref_ref.cloned().cloned(), Some(1)); } + +#[test] +fn test_try() { + fn try_option_some() -> Option<u8> { + let val = Some(1)?; + Some(val) + } + assert_eq!(try_option_some(), Some(1)); + + fn try_option_none() -> Option<u8> { + let val = None?; + Some(val) + } + assert_eq!(try_option_none(), None); + + fn try_option_ok() -> Result<u8, NoneError> { + let val = Some(1)?; + Ok(val) + } + assert_eq!(try_option_ok(), Ok(1)); + + fn try_option_err() -> Result<u8, NoneError> { + let val = None?; + Ok(val) + } + assert_eq!(try_option_err(), Err(NoneError)); +} diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index 4c5f19dee12..ce41bde8342 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::option::*; + fn op1() -> Result<isize, &'static str> { Ok(666) } fn op2() -> Result<isize, &'static str> { Err("sadface") } @@ -202,3 +204,30 @@ pub fn test_unwrap_or_default() { assert_eq!(op1().unwrap_or_default(), 666); assert_eq!(op2().unwrap_or_default(), 0); } + +#[test] +fn test_try() { + fn try_result_some() -> Option<u8> { + let val = Ok(1)?; + Some(val) + } + assert_eq!(try_result_some(), Some(1)); + + fn try_result_none() -> Option<u8> { + let val = Err(NoneError)?; + Some(val) + } + assert_eq!(try_result_none(), None); + + fn try_result_ok() -> Result<u8, u8> { + let val = Ok(1)?; + Ok(val) + } + assert_eq!(try_result_ok(), Ok(1)); + + fn try_result_err() -> Result<u8, u8> { + let val = Err(1)?; + Ok(val) + } + assert_eq!(try_result_err(), Err(1)); +} |
