diff options
Diffstat (limited to 'src/libcore')
57 files changed, 3333 insertions, 1011 deletions
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 178df02ccdd..5af63aa970f 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -9,9 +9,6 @@ path = "lib.rs" test = false bench = false -[dev-dependencies] -rand = { path = "../librand" } - [[test]] name = "coretests" path = "../libcore/tests/lib.rs" diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 6a7926fecde..3d24f8902bd 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -21,6 +21,7 @@ use borrow::{Borrow, BorrowMut}; use cmp::Ordering; +use convert::TryFrom; use fmt; use hash::{Hash, self}; use marker::Unsize; @@ -57,6 +58,30 @@ unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A { } } +/// The error type returned when a conversion from a slice to an array fails. +#[unstable(feature = "try_from", issue = "33417")] +#[derive(Debug, Copy, Clone)] +pub struct TryFromSliceError(()); + +impl fmt::Display for TryFromSliceError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.__description(), f) + } +} + +impl TryFromSliceError { + #[unstable(feature = "array_error_internals", + reason = "available through Error trait and this method should not \ + be exposed publicly", + issue = "0")] + #[inline] + #[doc(hidden)] + pub fn __description(&self) -> &str { + "could not convert slice to array" + } +} + macro_rules! __impl_slice_eq1 { ($Lhs: ty, $Rhs: ty) => { __impl_slice_eq1! { $Lhs, $Rhs, Sized } @@ -123,6 +148,34 @@ macro_rules! array_impls { } } + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> { + if slice.len() == $N { + let ptr = slice.as_ptr() as *const [T; $N]; + unsafe { Ok(&*ptr) } + } else { + Err(TryFromSliceError(())) + } + } + } + + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { + type Error = TryFromSliceError; + + fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> { + if slice.len() == $N { + let ptr = slice.as_mut_ptr() as *mut [T; $N]; + unsafe { Ok(&mut *ptr) } + } else { + Err(TryFromSliceError(())) + } + } + } + #[stable(feature = "rust1", since = "1.0.0")] impl<T: Hash> Hash for [T; $N] { fn hash<H: hash::Hasher>(&self, state: &mut H) { diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 827c6354c60..b284d855c45 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -147,40 +147,137 @@ 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) +} + +bench_sums! { + bench_take_while_chain_sum, + bench_take_while_chain_ref_sum, + (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111) } diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index d2db329da79..201064e823b 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -20,6 +20,6 @@ extern crate test; mod any; mod hash; mod iter; -mod mem; mod num; mod ops; +mod slice; diff --git a/src/libcore/benches/mem.rs b/src/libcore/benches/mem.rs deleted file mode 100644 index 8e541d92a7f..00000000000 --- a/src/libcore/benches/mem.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use test::Bencher; - -// FIXME #13642 (these benchmarks should be in another place) -// Completely miscellaneous language-construct benchmarks. -// Static/dynamic method dispatch - -struct Struct { - field: isize -} - -trait Trait { - fn method(&self) -> isize; -} - -impl Trait for Struct { - fn method(&self) -> isize { - self.field - } -} - -#[bench] -fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &Trait; - b.iter(|| { - t.method() - }); -} - -#[bench] -fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); -} - -// Overhead of various match forms - -#[bench] -fn match_option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| { - match x { - Some(y) => y, - None => 11 - } - }); -} - -#[bench] -fn match_vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; - b.iter(|| { - match x { - [1,2,3,..] => 10, - _ => 11, - } - }); -} diff --git a/src/libcore/benches/slice.rs b/src/libcore/benches/slice.rs new file mode 100644 index 00000000000..b2fc74544f1 --- /dev/null +++ b/src/libcore/benches/slice.rs @@ -0,0 +1,67 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use test::black_box; +use test::Bencher; + +enum Cache { + L1, + L2, + L3, +} + +fn binary_search<F>(b: &mut Bencher, cache: Cache, mapper: F) + where F: Fn(usize) -> usize +{ + let size = match cache { + Cache::L1 => 1000, // 8kb + Cache::L2 => 10_000, // 80kb + Cache::L3 => 1_000_000, // 8Mb + }; + let v = (0..size).map(&mapper).collect::<Vec<_>>(); + let mut r = 0usize; + b.iter(move || { + // LCG constants from https://en.wikipedia.org/wiki/Numerical_Recipes. + r = r.wrapping_mul(1664525).wrapping_add(1013904223); + // Lookup the whole range to get 50% hits and 50% misses. + let i = mapper(r % size); + black_box(v.binary_search(&i).is_ok()); + }) +} + +#[bench] +fn binary_search_l1(b: &mut Bencher) { + binary_search(b, Cache::L1, |i| i * 2); +} + +#[bench] +fn binary_search_l2(b: &mut Bencher) { + binary_search(b, Cache::L2, |i| i * 2); +} + +#[bench] +fn binary_search_l3(b: &mut Bencher) { + binary_search(b, Cache::L3, |i| i * 2); +} + +#[bench] +fn binary_search_l1_with_dups(b: &mut Bencher) { + binary_search(b, Cache::L1, |i| i / 16 * 16); +} + +#[bench] +fn binary_search_l2_with_dups(b: &mut Bencher) { + binary_search(b, Cache::L2, |i| i / 16 * 16); +} + +#[bench] +fn binary_search_l3_with_dups(b: &mut Bencher) { + binary_search(b, Cache::L3, |i| i / 16 * 16); +} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index b9c5ff10f87..d4cd3f6264e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -329,7 +329,6 @@ impl<T> Cell<T> { /// let c = Cell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_cell_new"))] #[inline] pub const fn new(value: T) -> Cell<T> { Cell { @@ -544,7 +543,6 @@ impl<T> RefCell<T> { /// let c = RefCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_refcell_new"))] #[inline] pub const fn new(value: T) -> RefCell<T> { RefCell { @@ -579,25 +577,51 @@ impl<T> RefCell<T> { /// /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html). /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + /// /// # Examples /// /// ``` /// #![feature(refcell_replace_swap)] /// use std::cell::RefCell; - /// let c = RefCell::new(5); - /// let u = c.replace(6); - /// assert_eq!(u, 5); - /// assert_eq!(c, RefCell::new(6)); + /// let cell = RefCell::new(5); + /// let old_value = cell.replace(6); + /// assert_eq!(old_value, 5); + /// assert_eq!(cell, RefCell::new(6)); /// ``` + #[inline] + #[unstable(feature = "refcell_replace_swap", issue="43570")] + pub fn replace(&self, t: T) -> T { + mem::replace(&mut *self.borrow_mut(), t) + } + + /// Replaces the wrapped value with a new one computed from `f`, returning + /// the old value, without deinitializing either one. + /// + /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html). /// /// # Panics /// - /// This function will panic if the `RefCell` has any outstanding borrows, - /// whether or not they are full mutable borrows. + /// Panics if the value is currently borrowed. + /// + /// # Examples + /// + /// ``` + /// #![feature(refcell_replace_swap)] + /// use std::cell::RefCell; + /// let cell = RefCell::new(5); + /// let old_value = cell.replace_with(|&mut old| old + 1); + /// assert_eq!(old_value, 5); + /// assert_eq!(cell, RefCell::new(6)); + /// ``` #[inline] #[unstable(feature = "refcell_replace_swap", issue="43570")] - pub fn replace(&self, t: T) -> T { - mem::replace(&mut *self.borrow_mut(), t) + pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T { + let mut_borrow = &mut *self.borrow_mut(); + let replacement = f(mut_borrow); + mem::replace(mut_borrow, replacement) } /// Swaps the wrapped value of `self` with the wrapped value of `other`, @@ -605,6 +629,10 @@ impl<T> RefCell<T> { /// /// This function corresponds to [`std::mem::swap`](../mem/fn.swap.html). /// + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently borrowed. + /// /// # Examples /// /// ``` @@ -616,11 +644,6 @@ impl<T> RefCell<T> { /// assert_eq!(c, RefCell::new(6)); /// assert_eq!(d, RefCell::new(5)); /// ``` - /// - /// # Panics - /// - /// This function will panic if either `RefCell` has any outstanding borrows, - /// whether or not they are full mutable borrows. #[inline] #[unstable(feature = "refcell_replace_swap", issue="43570")] pub fn swap(&self, other: &Self) { @@ -1190,7 +1213,6 @@ impl<T> UnsafeCell<T> { /// let uc = UnsafeCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_unsafe_cell_new"))] #[inline] pub const fn new(value: T) -> UnsafeCell<T> { UnsafeCell { value: value } diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs index 2c0f449b276..e6803745ab5 100644 --- a/src/libcore/char_private.rs +++ b/src/libcore/char_private.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -47,7 +47,7 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], current } -pub fn is_printable(x: char) -> bool { +pub(crate) fn is_printable(x: char) -> bool { let x = x as u32; let lower = x as u16; if x < 0x10000 { @@ -64,7 +64,10 @@ pub fn is_printable(x: char) -> bool { if 0x2b81e <= x && x < 0x2b820 { return false; } - if 0x2cea2 <= x && x < 0x2f800 { + if 0x2cea2 <= x && x < 0x2ceb0 { + return false; + } + if 0x2ebe1 <= x && x < 0x2f800 { return false; } if 0x2fa1e <= x && x < 0xe0100 { @@ -83,12 +86,12 @@ const SINGLETONS0U: &'static [(u8, u8)] = &[ (0x05, 8), (0x06, 3), (0x07, 4), - (0x08, 7), + (0x08, 8), (0x09, 16), (0x0a, 27), - (0x0b, 24), + (0x0b, 25), (0x0c, 22), - (0x0d, 20), + (0x0d, 18), (0x0e, 22), (0x0f, 4), (0x10, 3), @@ -99,16 +102,15 @@ const SINGLETONS0U: &'static [(u8, u8)] = &[ (0x18, 2), (0x19, 3), (0x1a, 7), - (0x1c, 1), + (0x1d, 1), (0x1f, 22), (0x20, 3), - (0x23, 1), (0x2b, 5), (0x2c, 2), (0x2d, 11), (0x2e, 1), (0x30, 3), - (0x31, 1), + (0x31, 3), (0x32, 2), (0xa7, 1), (0xa8, 2), @@ -125,19 +127,19 @@ const SINGLETONS0L: &'static [u8] = &[ 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x60, 0x88, 0x8b, 0x8c, 0x90, 0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0x2e, 0x2f, 0x3f, - 0x5c, 0x5d, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, - 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9, - 0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, 0x29, - 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, - 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, - 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, 0x04, - 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, - 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, - 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x04, - 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, - 0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, - 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, 0x0d, 0x11, - 0x3b, 0x3c, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81, + 0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, + 0x91, 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, + 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, + 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, + 0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, + 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, + 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, + 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, + 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, + 0xcf, 0x04, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, + 0x64, 0x65, 0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, + 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, + 0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x86, 0x89, 0x8b, 0x8c, 0x98, 0xa0, 0xa4, 0xa6, 0xa8, 0xa9, 0xac, 0xba, 0xbe, @@ -148,18 +150,18 @@ const SINGLETONS0L: &'static [u8] = &[ 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, - 0x7e, 0xae, 0xaf, 0xf7, 0x16, 0x17, 0x1e, 0x1f, + 0x7e, 0xae, 0xaf, 0xfa, 0x16, 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, - 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0xff, 0x74, 0x75, - 0x96, 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, - 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, - 0x9a, 0x40, 0x97, 0x98, 0x8f, 0x1f, 0xff, 0xaf, - 0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, - 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef, - 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, - 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, - 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, + 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, + 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, + 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, + 0x40, 0x97, 0x98, 0x2f, 0x30, 0x8f, 0x1f, 0xff, + 0xaf, 0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, + 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, + 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, + 0x90, 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, + 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, ]; const SINGLETONS1U: &'static [(u8, u8)] = &[ (0x00, 6), @@ -176,7 +178,9 @@ const SINGLETONS1U: &'static [(u8, u8)] = &[ (0x13, 18), (0x14, 2), (0x15, 2), + (0x1a, 3), (0x1c, 5), + (0x1d, 4), (0x24, 1), (0x6a, 3), (0x6b, 2), @@ -192,7 +196,7 @@ const SINGLETONS1U: &'static [(u8, u8)] = &[ (0xee, 32), (0xf0, 4), (0xf1, 1), - (0xf9, 4), + (0xf9, 1), ]; const SINGLETONS1L: &'static [u8] = &[ 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, @@ -202,18 +206,18 @@ const SINGLETONS1L: &'static [u8] = &[ 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, 0xb6, - 0xb7, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x6f, 0x5f, - 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, - 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, - 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, - 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, - 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5, - 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, - 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, - 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, - 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, - 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x1f, 0x31, - 0x32, 0x3f, + 0xb7, 0x84, 0x85, 0x9d, 0x09, 0x37, 0x90, 0x91, + 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x6f, 0x5f, 0xee, + 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, 0x55, + 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, + 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, + 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd, + 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5, 0xc6, + 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, + 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, 0x56, + 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, + 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, + 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x3f, ]; const NORMAL0: &'static [u8] = &[ 0x00, 0x20, @@ -224,12 +228,12 @@ const NORMAL0: &'static [u8] = &[ 0x05, 0x11, 0x81, 0xac, 0x0e, 0x3b, 0x05, - 0x5f, 0x41, + 0x6b, 0x35, 0x1e, 0x16, 0x80, 0xdf, 0x03, 0x19, 0x08, 0x01, 0x04, - 0x20, 0x05, + 0x22, 0x03, 0x0a, 0x04, 0x34, 0x04, 0x07, 0x03, @@ -238,8 +242,7 @@ const NORMAL0: &'static [u8] = &[ 0x10, 0x0b, 0x50, 0x0f, 0x12, 0x07, - 0x01, 0x07, - 0x4d, 0x08, + 0x55, 0x08, 0x02, 0x04, 0x1c, 0x0a, 0x09, 0x03, @@ -258,8 +261,8 @@ const NORMAL0: &'static [u8] = &[ 0x10, 0x08, 0x56, 0x07, 0x02, 0x07, - 0x15, 0x0e, - 0x4f, 0x04, + 0x15, 0x0d, + 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, @@ -304,34 +307,32 @@ const NORMAL0: &'static [u8] = &[ 0x3c, 0x37, 0x08, 0x08, 0x2a, 0x06, - 0x80, 0xf6, 0x05, - 0x82, 0x04, 0x11, + 0x82, 0xff, 0x11, 0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, - 0x1f, 0x11, + 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c, 0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x87, 0x5a, 0x03, - 0x15, 0x1a, + 0x16, 0x19, 0x04, 0x10, 0x80, 0xf4, 0x05, 0x2f, 0x05, 0x3b, 0x07, 0x02, 0x0e, 0x18, 0x09, - 0x80, 0xa5, 0x3b, + 0x80, 0xaa, 0x36, 0x74, 0x0c, 0x80, 0xd6, 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, - 0x29, 0x03, - 0x80, 0x8a, 0x05, + 0x80, 0xb6, 0x05, 0x24, 0x0c, 0x9b, 0xc6, 0x0a, - 0xd2, 0x16, 0x2a, + 0xd2, 0x2b, 0x15, 0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, @@ -378,8 +379,8 @@ const NORMAL1: &'static [u8] = &[ 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, - 0x24, 0x0c, - 0x1b, 0x05, + 0x24, 0x09, + 0x1e, 0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, @@ -447,11 +448,16 @@ const NORMAL1: &'static [u8] = &[ 0x0f, 0x04, 0x10, 0x81, 0x60, 0x53, 0x0c, - 0x01, 0x81, 0xc0, + 0x01, 0x81, 0x00, + 0x48, 0x08, + 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03, - 0x47, 0x83, 0x49, + 0x47, 0x49, + 0x37, 0x03, + 0x0e, 0x08, + 0x0a, 0x82, 0xa6, 0x83, 0x9a, 0x66, 0x75, 0x0b, 0x80, 0xc4, 0x8a, 0xbc, @@ -467,10 +473,11 @@ const NORMAL1: &'static [u8] = &[ 0x45, 0x0b, 0x2f, 0x10, 0x11, 0x40, - 0x01, 0x1f, + 0x02, 0x1e, 0x97, 0xed, 0x13, 0x82, 0xf3, 0xa5, 0x0d, - 0x02, 0x8b, 0xfe, + 0x81, 0x1f, 0x51, + 0x81, 0x8c, 0x89, 0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, @@ -503,20 +510,22 @@ const NORMAL1: &'static [u8] = &[ 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, - 0x02, 0x80, 0xae, - 0x83, 0xd3, 0x0d, + 0x02, 0x0e, + 0x06, 0x80, 0x9a, + 0x83, 0xd5, 0x0b, 0x0d, 0x03, - 0x07, 0x09, + 0x09, 0x07, 0x74, 0x0c, 0x55, 0x2b, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, - 0x1e, 0x62, - 0x18, 0x08, - 0x1c, 0x04, - 0x0f, 0x21, - 0x12, 0x2e, - 0x01, 0x86, 0x3f, + 0x1e, 0x52, + 0x0c, 0x04, + 0x3d, 0x03, + 0x1c, 0x14, + 0x18, 0x28, + 0x01, 0x0f, + 0x17, 0x86, 0x19, ]; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6f86f8caad0..cc71e09caea 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -162,8 +162,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Eq: PartialEq<Self> { - // FIXME #13101: this method is used solely by #[deriving] to - // assert that every component of a type implements #[deriving] + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] // itself, the current deriving infrastructure means doing this // assertion without using a method on this trait is nearly // impossible. @@ -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/builders.rs b/src/libcore/fmt/builders.rs index b594c886b64..60b9eeb1283 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use fmt::{self, FlagV1}; +use fmt; struct PadAdapter<'a, 'b: 'a> { fmt: &'a mut fmt::Formatter<'b>, @@ -140,7 +140,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } @@ -233,7 +233,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } @@ -277,7 +277,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } @@ -519,6 +519,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index b84a1deb611..551aa929ce4 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -261,6 +261,14 @@ pub struct Formatter<'a> { struct Void { _priv: (), + /// Erases all oibits, because `Void` erases the type of the object that + /// will be used to produce formatted output. Since we do not know what + /// oibits the real types have (and they can have any or none), we need to + /// take the most conservative approach and forbid all oibits. + /// + /// It was added after #45197 showed that one could share a `!Sync` + /// object across threads by passing it into `format_args!`. + _oibit_remover: PhantomData<*mut Fn()>, } /// This struct represents the generic "argument" which is taken by the Xprintf @@ -322,7 +330,6 @@ impl<'a> ArgumentV1<'a> { // flags available in the v1 format of format_args #[derive(Copy, Clone)] -#[allow(dead_code)] // SignMinus isn't currently used enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, } impl<'a> Arguments<'a> { @@ -427,7 +434,7 @@ impl<'a> Display for Arguments<'a> { } } -/// Format trait for the `?` character. +/// `?` formatting. /// /// `Debug` should format the output in a programmer-facing, debugging context. /// @@ -488,13 +495,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 `#?`: /// @@ -525,6 +533,26 @@ impl<'a> Display for Arguments<'a> { #[lang = "debug_trait"] pub trait Debug { /// Formats the value using the given formatter. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Position { + /// longitude: f32, + /// latitude: f32, + /// } + /// + /// impl fmt::Debug for Position { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "({:?}, {:?})", self.longitude, self.latitude) + /// } + /// } + /// + /// assert_eq!("(1.987, 2.983)".to_owned(), + /// format!("{:?}", Position { longitude: 1.987, latitude: 2.983, })); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, f: &mut Formatter) -> Result; } @@ -592,10 +620,13 @@ pub trait Display { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `o` character. +/// `o` formatting. /// /// The `Octal` trait should format its output as a number in base-8. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0o` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -611,6 +642,8 @@ pub trait Display { /// /// assert_eq!(format!("{:o}", x), "52"); /// assert_eq!(format!("{:#o}", x), "0o52"); +/// +/// assert_eq!(format!("{:o}", -16), "37777777760"); /// ``` /// /// Implementing `Octal` on a type: @@ -639,10 +672,13 @@ pub trait Octal { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `b` character. +/// `b` formatting. /// /// The `Binary` trait should format its output as a number in binary. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0b` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -658,6 +694,8 @@ pub trait Octal { /// /// assert_eq!(format!("{:b}", x), "101010"); /// assert_eq!(format!("{:#b}", x), "0b101010"); +/// +/// assert_eq!(format!("{:b}", -16), "11111111111111111111111111110000"); /// ``` /// /// Implementing `Binary` on a type: @@ -686,11 +724,14 @@ pub trait Binary { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `x` character. +/// `x` formatting. /// /// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` /// in lower case. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0x` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -706,6 +747,8 @@ pub trait Binary { /// /// assert_eq!(format!("{:x}", x), "2a"); /// assert_eq!(format!("{:#x}", x), "0x2a"); +/// +/// assert_eq!(format!("{:x}", -16), "fffffff0"); /// ``` /// /// Implementing `LowerHex` on a type: @@ -734,11 +777,14 @@ pub trait LowerHex { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `X` character. +/// `X` formatting. /// /// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` /// in upper case. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0x` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -754,6 +800,8 @@ pub trait LowerHex { /// /// assert_eq!(format!("{:X}", x), "2A"); /// assert_eq!(format!("{:#X}", x), "0x2A"); +/// +/// assert_eq!(format!("{:X}", -16), "FFFFFFF0"); /// ``` /// /// Implementing `UpperHex` on a type: @@ -782,7 +830,7 @@ pub trait UpperHex { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `p` character. +/// `p` formatting. /// /// The `Pointer` trait should format its output as a memory location. This is commonly presented /// as hexadecimal. @@ -827,7 +875,7 @@ pub trait Pointer { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `e` character. +/// `e` formatting. /// /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`. /// @@ -870,7 +918,7 @@ pub trait LowerExp { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `E` character. +/// `E` formatting. /// /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`. /// @@ -932,7 +980,7 @@ pub trait UpperExp { /// assert_eq!(output, "Hello world!"); /// ``` /// -/// Please note that using [`write!`] might be preferrable. Example: +/// Please note that using [`write!`] might be preferable. Example: /// /// ``` /// use std::fmt::Write; @@ -1275,8 +1323,11 @@ impl<'a> Formatter<'a> { write(self.buf, fmt) } - /// Flags for formatting (packed version of rt::Flag) + /// Flags for formatting #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.24.0", + reason = "use the `sign_plus`, `sign_minus`, `alternate`, \ + or `sign_aware_zero_pad` methods instead")] pub fn flags(&self) -> u32 { self.flags } /// Character used as 'fill' whenever there is alignment @@ -1321,8 +1372,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 /// diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 8ea388fddf8..ee989854a37 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -12,7 +12,6 @@ #![allow(deprecated)] -// FIXME: #6220 Implement floating point formatting use fmt; use ops::{Div, Rem, Sub}; @@ -135,7 +134,7 @@ macro_rules! radix { } } -radix! { Binary, 2, "0b", x @ 0 ... 2 => b'0' + x } +radix! { Binary, 2, "0b", x @ 0 ... 1 => b'0' + x } radix! { Octal, 8, "0o", x @ 0 ... 7 => b'0' + x } radix! { Decimal, 10, "", x @ 0 ... 9 => b'0' + x } radix! { LowerHex, 16, "0x", x @ 0 ... 9 => b'0' + x, diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index bc1b911cd78..15545a04b64 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -259,7 +259,7 @@ pub trait Hasher { /// println!("Hash is {:x}!", hasher.finish()); /// ``` /// - /// ['write']: #tymethod.write + /// [`write`]: #tymethod.write #[stable(feature = "rust1", since = "1.0.0")] fn finish(&self) -> u64; @@ -665,16 +665,36 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl<T> Hash for *const T { + impl<T: ?Sized> Hash for *const T { fn hash<H: Hasher>(&self, state: &mut H) { - state.write_usize(*self as usize) + if mem::size_of::<Self>() == mem::size_of::<usize>() { + // Thin pointer + state.write_usize(*self as *const () as usize); + } else { + // Fat pointer + let (a, b) = unsafe { + *(self as *const Self as *const (usize, usize)) + }; + state.write_usize(a); + state.write_usize(b); + } } } #[stable(feature = "rust1", since = "1.0.0")] - impl<T> Hash for *mut T { + impl<T: ?Sized> Hash for *mut T { fn hash<H: Hasher>(&self, state: &mut H) { - state.write_usize(*self as usize) + if mem::size_of::<Self>() == mem::size_of::<usize>() { + // Thin pointer + state.write_usize(*self as *const () as usize); + } else { + // Fat pointer + let (a, b) = unsafe { + *(self as *const Self as *const (usize, usize)) + }; + state.write_usize(a); + state.write_usize(b); + } } } } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 91fd01b36d4..4e4d9b3f1e2 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -22,7 +22,7 @@ use mem; /// This is currently the default hashing function used by standard library /// (eg. `collections::HashMap` uses it by default). /// -/// See: https://131002.net/siphash/ +/// See: <https://131002.net/siphash> #[unstable(feature = "sip_hash_13", issue = "34767")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] @@ -33,7 +33,7 @@ pub struct SipHasher13 { /// An implementation of SipHash 2-4. /// -/// See: https://131002.net/siphash/ +/// See: <https://131002.net/siphash/> #[unstable(feature = "sip_hash_13", issue = "34767")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] @@ -44,7 +44,7 @@ pub struct SipHasher24 { /// An implementation of SipHash 2-4. /// -/// See: https://131002.net/siphash/ +/// See: <https://131002.net/siphash/> /// /// SipHash is a general-purpose hashing function: it runs at a good /// speed (competitive with Spooky and City) and permits strong _keyed_ @@ -72,6 +72,7 @@ struct Hasher<S: Sip> { } #[derive(Debug, Clone, Copy)] +#[repr(C)] struct State { // v0, v2 and v1, v3 show up in pairs in the algorithm, // and simd implementations of SipHash will use vectors 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/intrinsics.rs b/src/libcore/intrinsics.rs index bc82f0230e5..f1e51e995c2 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -627,6 +627,9 @@ extern "rust-intrinsic" { pub fn rustc_peek<T>(_: T) -> T; /// Aborts the execution of the process. + /// + /// The stabilized version of this intrinsic is + /// [`std::process::abort`](../../std/process/fn.abort.html) pub fn abort() -> !; /// Tells LLVM that this point in the code is not reachable, enabling @@ -676,6 +679,10 @@ extern "rust-intrinsic" { pub fn min_align_of<T>() -> usize; pub fn pref_align_of<T>() -> usize; + /// The size of the referenced value in bytes. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html). pub fn size_of_val<T: ?Sized>(_: &T) -> usize; pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize; @@ -921,6 +928,9 @@ extern "rust-intrinsic" { /// /// If the actual type neither requires drop glue nor implements /// `Copy`, then may return `true` or `false`. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html). pub fn needs_drop<T>() -> bool; /// Calculates the offset from a pointer. @@ -1376,17 +1386,10 @@ extern "rust-intrinsic" { /// } /// # } } /// ``` - #[cfg(not(stage0))] pub fn align_offset(ptr: *const (), align: usize) -> usize; -} -#[cfg(stage0)] -/// remove me after the next release -pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize { - let offset = ptr as usize % align; - if offset == 0 { - 0 - } else { - align - offset - } + /// Emits a `!nontemporal` store according to LLVM (see their docs). + /// Probably will never become stable. + #[cfg(not(stage0))] + pub fn nontemporal_store<T>(ptr: *mut T, val: T); } diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 36bf9633b4a..7f6d627536d 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -9,7 +9,9 @@ // except according to those terms. use cmp::Ordering; +use ops::Try; +use super::{AlwaysOk, LoopState}; use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse}; use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev}; use super::{Zip, Sum, Product}; @@ -28,6 +30,7 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \ `.iter()` or a similar method"] +#[doc(spotlight)] pub trait Iterator { /// The type of the elements being iterated over. #[stable(feature = "rust1", since = "1.0.0")] @@ -518,7 +521,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,6 +1340,78 @@ pub trait Iterator { (left, right) } + /// An iterator method that applies a function as long as it returns + /// successfully, producing a single, final value. + /// + /// `try_fold()` takes two arguments: an initial value, and a closure with + /// two arguments: an 'accumulator', and an element. The closure either + /// returns successfully, with the value that the accumulator should have + /// for the next iteration, or it returns failure, with an error value that + /// is propagated back to the caller immediately (short-circuiting). + /// + /// The initial value is the value the accumulator will have on the first + /// call. If applying the closure succeeded against every element of the + /// iterator, `try_fold()` returns the final accumulator as success. + /// + /// Folding is useful whenever you have a collection of something, and want + /// to produce a single value from it. + /// + /// # Note to Implementors + /// + /// Most of the other (forward) methods have default implementations in + /// terms of this one, so try to implement this explicitly if it can + /// do something better than the default `for` loop implementation. + /// + /// In particular, try to have this call `try_fold()` on the internal parts + /// from which this iterator is composed. If multiple calls are needed, + /// the `?` operator be convenient for chaining the accumulator value along, + /// but beware any invariants that need to be upheld before those early + /// returns. This is a `&mut self` method, so iteration needs to be + /// resumable after hitting an error here. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iterator_try_fold)] + /// let a = [1, 2, 3]; + /// + /// // the checked sum of all of the elements of the array + /// let sum = a.iter() + /// .try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// + /// assert_eq!(sum, Some(6)); + /// ``` + /// + /// Short-circuiting: + /// + /// ``` + /// #![feature(iterator_try_fold)] + /// let a = [10, 20, 30, 100, 40, 50]; + /// let mut it = a.iter(); + /// + /// // This sum overflows when adding the 100 element + /// let sum = it.try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// assert_eq!(sum, None); + /// + /// // Because it short-circuited, the remaining elements are still + /// // available through the iterator. + /// assert_eq!(it.len(), 2); + /// assert_eq!(it.next(), Some(&40)); + /// ``` + #[inline] + #[unstable(feature = "iterator_try_fold", issue = "45594")] + fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + Try::from_ok(accum) + } + /// An iterator method that applies a function, producing a single, final value. /// /// `fold()` takes two arguments: an initial value, and a closure with two @@ -1361,7 +1436,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// // the sum of all of the elements of a + /// // the sum of all of the elements of the array /// let sum = a.iter() /// .fold(0, |acc, &x| acc + x); /// @@ -1403,14 +1478,10 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn fold<B, F>(self, init: B, mut f: F) -> B where + fn fold<B, F>(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - let mut accum = init; - for x in self { - accum = f(accum, x); - } - accum + self.try_fold(init, move |acc, x| AlwaysOk(f(acc, x))).0 } /// Tests if every element of the iterator matches a predicate. @@ -1455,12 +1526,10 @@ pub trait Iterator { fn all<F>(&mut self, mut f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - for x in self { - if !f(x) { - return false; - } - } - true + self.try_fold((), move |(), x| { + if f(x) { LoopState::Continue(()) } + else { LoopState::Break(()) } + }) == LoopState::Continue(()) } /// Tests if any element of the iterator matches a predicate. @@ -1506,12 +1575,10 @@ pub trait Iterator { Self: Sized, F: FnMut(Self::Item) -> bool { - for x in self { - if f(x) { - return true; - } - } - false + self.try_fold((), move |(), x| { + if f(x) { LoopState::Break(()) } + else { LoopState::Continue(()) } + }) == LoopState::Break(()) } /// Searches for an element of an iterator that satisfies a predicate. @@ -1562,10 +1629,10 @@ pub trait Iterator { Self: Sized, P: FnMut(&Self::Item) -> bool, { - for x in self { - if predicate(&x) { return Some(x) } - } - None + self.try_fold((), move |(), x| { + if predicate(&x) { LoopState::Break(x) } + else { LoopState::Continue(()) } + }).break_value() } /// Searches for an element in an iterator, returning its index. @@ -1623,18 +1690,17 @@ pub trait Iterator { /// /// ``` #[inline] + #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] fn position<P>(&mut self, mut predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, { - // `enumerate` might overflow. - for (i, x) in self.enumerate() { - if predicate(x) { - return Some(i); - } - } - None + // The addition might panic on overflow + self.try_fold(0, move |i, x| { + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(i + 1) } + }).break_value() } /// Searches for an element in an iterator from the right, returning its @@ -1681,17 +1747,14 @@ pub trait Iterator { P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator { - let mut i = self.len(); - - while let Some(v) = self.next_back() { - // No need for an overflow check here, because `ExactSizeIterator` - // implies that the number of elements fits into a `usize`. - i -= 1; - if predicate(v) { - return Some(i); - } - } - None + // No need for an overflow check here, because `ExactSizeIterator` + // implies that the number of elements fits into a `usize`. + let n = self.len(); + self.try_rfold(n, move |i, x| { + let i = i - 1; + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(i) } + }).break_value() } /// Returns the maximum element of an iterator. @@ -1922,10 +1985,10 @@ pub trait Iterator { let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); - for (t, u) in self { + self.for_each(|(t, u)| { ts.extend(Some(t)); us.extend(Some(u)); - } + }); (ts, us) } @@ -2059,14 +2122,23 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return Ordering::Equal, - (None, _ ) => return Ordering::Less, - (_ , None) => return Ordering::Greater, - (Some(x), Some(y)) => match x.cmp(&y) { - Ordering::Equal => (), - non_eq => return non_eq, + let x = match self.next() { + None => if other.next().is_none() { + return Ordering::Equal + } else { + return Ordering::Less }, + Some(val) => val, + }; + + let y = match other.next() { + None => return Ordering::Greater, + Some(val) => val, + }; + + match x.cmp(&y) { + Ordering::Equal => (), + non_eq => return non_eq, } } } @@ -2082,14 +2154,23 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return Some(Ordering::Equal), - (None, _ ) => return Some(Ordering::Less), - (_ , None) => return Some(Ordering::Greater), - (Some(x), Some(y)) => match x.partial_cmp(&y) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, + let x = match self.next() { + None => if other.next().is_none() { + return Some(Ordering::Equal) + } else { + return Some(Ordering::Less) }, + Some(val) => val, + }; + + let y = match other.next() { + None => return Some(Ordering::Greater), + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Equal) => (), + non_eq => return non_eq, } } } @@ -2105,11 +2186,17 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return true, - (None, _) | (_, None) => return false, - (Some(x), Some(y)) => if x != y { return false }, - } + let x = match self.next() { + None => return other.next().is_none(), + Some(val) => val, + }; + + let y = match other.next() { + None => return false, + Some(val) => val, + }; + + if x != y { return false } } } @@ -2124,11 +2211,17 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return false, - (None, _) | (_, None) => return true, - (Some(x), Some(y)) => if x.ne(&y) { return true }, - } + let x = match self.next() { + None => return other.next().is_some(), + Some(val) => val, + }; + + let y = match other.next() { + None => return true, + Some(val) => val, + }; + + if x != y { return true } } } @@ -2143,18 +2236,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return false, - (None, _ ) => return true, - (_ , None) => return false, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return true, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return false, - None => return false, - } - }, + let x = match self.next() { + None => return other.next().is_some(), + Some(val) => val, + }; + + let y = match other.next() { + None => return false, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return true, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return false, + None => return false, } } } @@ -2170,18 +2266,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return true, - (None, _ ) => return true, - (_ , None) => return false, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return true, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return false, - None => return false, - } - }, + let x = match self.next() { + None => { other.next(); return true; }, + Some(val) => val, + }; + + let y = match other.next() { + None => return false, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return true, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return false, + None => return false, } } } @@ -2197,18 +2296,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return false, - (None, _ ) => return false, - (_ , None) => return true, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return false, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return true, - None => return false, - } - } + let x = match self.next() { + None => { other.next(); return false; }, + Some(val) => val, + }; + + let y = match other.next() { + None => return true, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return false, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return true, + None => return false, } } } @@ -2224,18 +2326,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return true, - (None, _ ) => return false, - (_ , None) => return true, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return false, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return true, - None => return false, - } - }, + let x = match self.next() { + None => return other.next().is_none(), + Some(val) => val, + }; + + let y = match other.next() { + None => return true, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return false, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return true, + None => return false, } } } @@ -2258,17 +2363,17 @@ fn select_fold1<I, B, FProj, FCmp>(mut it: I, // start with the first element as our selection. This avoids // having to use `Option`s inside the loop, translating to a // sizeable performance gain (6x in one case). - it.next().map(|mut sel| { - let mut sel_p = f_proj(&sel); + it.next().map(|first| { + let first_p = f_proj(&first); - for x in it { + it.fold((first_p, first), |(sel_p, sel), x| { let x_p = f_proj(&x); if f_cmp(&sel_p, &sel, &x_p, &x) { - sel = x; - sel_p = x_p; + (x_p, x) + } else { + (sel_p, sel) } - } - (sel_p, sel) + }) }) } diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 2d3ff6a348d..e173f43b5e6 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -305,6 +305,7 @@ use cmp; use fmt; use iter_private::TrustedRandomAccess; +use ops::Try; use usize; #[stable(feature = "rust1", since = "1.0.0")] @@ -336,6 +337,71 @@ mod range; mod sources; mod traits; +/// Transparent newtype used to implement foo methods in terms of try_foo. +/// Important until #43278 is fixed; might be better as `Result<T, !>` later. +struct AlwaysOk<T>(pub T); + +impl<T> Try for AlwaysOk<T> { + type Ok = T; + type Error = !; + #[inline] + fn into_result(self) -> Result<Self::Ok, Self::Error> { Ok(self.0) } + #[inline] + fn from_error(v: Self::Error) -> Self { v } + #[inline] + fn from_ok(v: Self::Ok) -> Self { AlwaysOk(v) } +} + +/// Used to make try_fold closures more like normal loops +#[derive(PartialEq)] +enum LoopState<C, B> { + Continue(C), + Break(B), +} + +impl<C, B> Try for LoopState<C, B> { + type Ok = C; + type Error = B; + #[inline] + fn into_result(self) -> Result<Self::Ok, Self::Error> { + match self { + LoopState::Continue(y) => Ok(y), + LoopState::Break(x) => Err(x), + } + } + #[inline] + fn from_error(v: Self::Error) -> Self { LoopState::Break(v) } + #[inline] + fn from_ok(v: Self::Ok) -> Self { LoopState::Continue(v) } +} + +impl<C, B> LoopState<C, B> { + #[inline] + fn break_value(self) -> Option<B> { + match self { + LoopState::Continue(..) => None, + LoopState::Break(x) => Some(x), + } + } +} + +impl<R: Try> LoopState<R::Ok, R> { + #[inline] + fn from_try(r: R) -> Self { + match Try::into_result(r) { + Ok(v) => LoopState::Continue(v), + Err(v) => LoopState::Break(Try::from_error(v)), + } + } + #[inline] + fn into_try(self) -> R { + match self { + LoopState::Continue(v) => Try::from_ok(v), + LoopState::Break(v) => v, + } + } +} + /// A double-ended iterator with the direction inverted. /// /// This `struct` is created by the [`rev`] method on [`Iterator`]. See its @@ -359,6 +425,12 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + self.iter.try_rfold(init, f) + } + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -385,6 +457,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 try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + self.iter.try_fold(init, f) + } + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -447,6 +525,12 @@ impl<'a, I, T: 'a> Iterator for Cloned<I> self.it.size_hint() } + fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + self.it.try_fold(init, move |acc, elt| f(acc, elt.clone())) + } + fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -462,6 +546,12 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> self.it.next_back().cloned() } + fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone())) + } + fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -558,7 +648,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. @@ -683,6 +773,25 @@ impl<A, B> Iterator for Chain<A, B> where } } + fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where + Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.try_fold(accum, &mut f)?; + if let ChainState::Both = self.state { + self.state = ChainState::Back; + } + } + _ => { } + } + if let ChainState::Back = self.state { + accum = self.b.try_fold(accum, &mut f)?; + } + Try::from_ok(accum) + } + fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -792,6 +901,25 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where } } + fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where + Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.try_rfold(accum, &mut f)?; + if let ChainState::Both = self.state { + self.state = ChainState::Front; + } + } + _ => { } + } + if let ChainState::Front = self.state { + accum = self.a.try_rfold(accum, &mut f)?; + } + Try::from_ok(accum) + } + fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -1128,6 +1256,13 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B { self.iter.size_hint() } + fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where + Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let f = &mut self.f; + self.iter.try_fold(init, move |acc, elt| g(acc, f(elt))) + } + fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { @@ -1145,6 +1280,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where self.iter.next_back().map(&mut self.f) } + fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where + Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let f = &mut self.f; + self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt))) + } + fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { @@ -1250,6 +1392,30 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool } count } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let predicate = &mut self.predicate; + self.iter.try_fold(init, move |acc, item| if predicate(&item) { + fold(acc, item) + } else { + Try::from_ok(acc) + }) + } + + #[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")] @@ -1265,6 +1431,30 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> } None } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let predicate = &mut self.predicate; + self.iter.try_rfold(init, move |acc, item| if predicate(&item) { + fold(acc, item) + } else { + Try::from_ok(acc) + }) + } + + #[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")] @@ -1316,6 +1506,28 @@ 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 try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let f = &mut self.f; + self.iter.try_fold(init, move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => Try::from_ok(acc), + }) + } + + #[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")] @@ -1331,6 +1543,28 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> } None } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let f = &mut self.f; + self.iter.try_rfold(init, move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => Try::from_ok(acc), + }) + } + + #[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")] @@ -1395,6 +1629,32 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { fn count(self) -> usize { self.iter.count() } + + #[inline] + #[rustc_inherit_overflow_checks] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let count = &mut self.count; + self.iter.try_fold(init, move |acc, item| { + let acc = fold(acc, (*count, item)); + *count += 1; + acc + }) + } + + #[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")] @@ -1410,6 +1670,32 @@ impl<I> DoubleEndedIterator for Enumerate<I> where (self.count + len, a) }) } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=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.try_rfold(init, move |acc, item| { + count -= 1; + fold(acc, (count, item)) + }) + } + + #[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")] @@ -1521,6 +1807,30 @@ impl<I: Iterator> Iterator for Peekable<I> { let hi = hi.and_then(|x| x.checked_add(peek_len)); (lo, hi) } + + #[inline] + fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + let acc = match self.peeked.take() { + Some(None) => return Try::from_ok(init), + Some(Some(v)) => f(init, v)?, + None => init, + }; + self.iter.try_fold(acc, f) + } + + #[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")] @@ -1615,13 +1925,16 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P> #[inline] fn next(&mut self) -> Option<I::Item> { - for x in self.iter.by_ref() { - if self.flag || !(self.predicate)(&x) { - self.flag = true; - return Some(x); + let flag = &mut self.flag; + let pred = &mut self.predicate; + self.iter.find(move |x| { + if *flag || !pred(x) { + *flag = true; + true + } else { + false } - } - None + }) } #[inline] @@ -1629,6 +1942,32 @@ 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 try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if !self.flag { + match self.next() { + Some(v) => init = fold(init, v)?, + None => return Try::from_ok(init), + } + } + self.iter.try_fold(init, fold) + } + + #[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")] @@ -1688,6 +2027,26 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P> let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if self.flag { + Try::from_ok(init) + } else { + let flag = &mut self.flag; + let p = &mut self.predicate; + self.iter.try_fold(init, move |acc, x|{ + if p(&x) { + LoopState::from_try(fold(acc, x)) + } else { + *flag = true; + LoopState::Break(Try::from_ok(acc)) + } + }).into_try() + } + } } #[unstable(feature = "fused", issue = "35602")] @@ -1769,6 +2128,34 @@ impl<I> Iterator for Skip<I> where I: Iterator { (lower, upper) } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let n = self.n; + self.n = 0; + if n > 0 { + // nth(n) skips n+1 + if self.iter.nth(n - 1).is_none() { + return Try::from_ok(init); + } + } + self.iter.try_fold(init, fold) + } + + #[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")] @@ -1783,6 +2170,22 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize None } } + + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let mut n = self.len(); + if n == 0 { + Try::from_ok(init) + } else { + self.iter.try_rfold(init, move |acc, x| { + n -= 1; + let r = fold(acc, x); + if n == 0 { LoopState::Break(r) } + else { LoopState::from_try(r) } + }).into_try() + } + } } #[unstable(feature = "fused", issue = "35602")] @@ -1844,6 +2247,23 @@ impl<I> Iterator for Take<I> where I: Iterator{ (lower, upper) } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if self.n == 0 { + Try::from_ok(init) + } else { + let n = &mut self.n; + self.iter.try_fold(init, move |acc, x| { + *n -= 1; + let r = fold(acc, x); + if *n == 0 { LoopState::Break(r) } + else { LoopState::from_try(r) } + }).into_try() + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1895,6 +2315,20 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the scan function } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let state = &mut self.state; + let f = &mut self.f; + self.iter.try_fold(init, move |acc, x| { + match f(state, x) { + None => LoopState::Break(Try::from_ok(acc)), + Some(x) => LoopState::from_try(fold(acc, x)), + } + }).into_try() + } } /// An iterator that maps each element to an iterator, and yields the elements @@ -1961,6 +2395,35 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F> } #[inline] + fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if let Some(ref mut front) = self.frontiter { + init = front.try_fold(init, &mut fold)?; + } + self.frontiter = None; + + { + let f = &mut self.f; + let frontiter = &mut self.frontiter; + init = self.iter.try_fold(init, |acc, x| { + let mut mid = f(x).into_iter(); + let r = mid.try_fold(acc, &mut fold); + *frontiter = Some(mid); + r + })?; + } + self.frontiter = None; + + if let Some(ref mut back) = self.backiter { + init = back.try_fold(init, &mut fold)?; + } + self.backiter = None; + + Try::from_ok(init) + } + + #[inline] fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { @@ -1991,6 +2454,45 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher } } } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if let Some(ref mut back) = self.backiter { + init = back.try_rfold(init, &mut fold)?; + } + self.backiter = None; + + { + let f = &mut self.f; + let backiter = &mut self.backiter; + init = self.iter.try_rfold(init, |acc, x| { + let mut mid = f(x).into_iter(); + let r = mid.try_rfold(acc, &mut fold); + *backiter = Some(mid); + r + })?; + } + self.backiter = None; + + if let Some(ref mut front) = self.frontiter { + init = front.try_rfold(init, &mut fold)?; + } + self.frontiter = None; + + Try::from_ok(init) + } + + #[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")] @@ -2068,6 +2570,30 @@ impl<I> Iterator for Fuse<I> where I: Iterator { self.iter.size_hint() } } + + #[inline] + default fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if self.done { + Try::from_ok(init) + } else { + let acc = self.iter.try_fold(init, fold)?; + self.done = true; + Try::from_ok(acc) + } + } + + #[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")] @@ -2082,6 +2608,30 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator { next } } + + #[inline] + default fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + if self.done { + Try::from_ok(init) + } else { + let acc = self.iter.try_rfold(init, fold)?; + self.done = true; + Try::from_ok(acc) + } + } + + #[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> @@ -2122,6 +2672,20 @@ impl<I> Iterator for Fuse<I> where I: FusedIterator { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + self.iter.try_fold(init, fold) + } + + #[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")] @@ -2132,6 +2696,20 @@ impl<I> DoubleEndedIterator for Fuse<I> fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + self.iter.try_rfold(init, fold) + } + + #[inline] + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, fold) + } } @@ -2196,6 +2774,22 @@ 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 try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let f = &mut self.f; + self.iter.try_fold(init, move |acc, item| { f(&item); fold(acc, item) }) + } + + #[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")] @@ -2207,6 +2801,22 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F> let next = self.iter.next_back(); self.do_inspect(next) } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + let f = &mut self.f; + self.iter.try_rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + } + + #[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 28236d193c3..11e668d228c 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -7,9 +7,11 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use ops::{Mul, Add}; +use ops::{Mul, Add, Try}; use num::Wrapping; +use super::{AlwaysOk, LoopState}; + /// Conversion from an `Iterator`. /// /// By implementing `FromIterator` for a type, you define how it will be @@ -415,6 +417,52 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option<Self::Item>; + /// This is the reverse version of [`try_fold()`]: it takes elements + /// starting from the back of the iterator. + /// + /// [`try_fold()`]: trait.Iterator.html#method.try_fold + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iterator_try_fold)] + /// let a = ["1", "2", "3"]; + /// let sum = a.iter() + /// .map(|&s| s.parse::<i32>()) + /// .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y))); + /// assert_eq!(sum, Ok(6)); + /// ``` + /// + /// Short-circuiting: + /// + /// ``` + /// #![feature(iterator_try_fold)] + /// let a = ["1", "rust", "3"]; + /// let mut it = a.iter(); + /// let sum = it + /// .by_ref() + /// .map(|&s| s.parse::<i32>()) + /// .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y))); + /// assert!(sum.is_err()); + /// + /// // Because it short-circuited, the remaining elements are still + /// // available through the iterator. + /// assert_eq!(it.next_back(), Some(&"1")); + /// ``` + #[inline] + #[unstable(feature = "iterator_try_fold", issue = "45594")] + fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + Try::from_ok(accum) + } + /// An iterator method that reduces the iterator's elements to a single, /// final value, starting from the back. /// @@ -470,13 +518,10 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[unstable(feature = "iter_rfold", issue = "44705")] - fn rfold<B, F>(mut self, mut accum: B, mut f: F) -> B where + fn rfold<B, F>(mut self, 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 + self.try_rfold(accum, move |acc, x| AlwaysOk(f(acc, x))).0 } /// Searches for an element of an iterator from the right that satisfies a predicate. @@ -531,10 +576,10 @@ pub trait DoubleEndedIterator: Iterator { Self: Sized, P: FnMut(&Self::Item) -> bool { - while let Some(x) = self.next_back() { - if predicate(&x) { return Some(x) } - } - None + self.try_rfold((), move |(), x| { + if predicate(&x) { LoopState::Break(x) } + else { LoopState::Continue(()) } + }).break_value() } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 69612bd2a32..d5190b65863 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -85,29 +85,12 @@ #![feature(prelude_import)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] -#![cfg_attr(not(stage0), feature(rustc_const_unstable))] #![feature(specialization)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(untagged_unions)] #![feature(unwind_attributes)] - -#![cfg_attr(not(stage0), feature(const_min_value))] -#![cfg_attr(not(stage0), feature(const_max_value))] -#![cfg_attr(not(stage0), feature(const_atomic_bool_new))] -#![cfg_attr(not(stage0), feature(const_atomic_isize_new))] -#![cfg_attr(not(stage0), feature(const_atomic_usize_new))] -#![cfg_attr(not(stage0), feature(const_atomic_i8_new))] -#![cfg_attr(not(stage0), feature(const_atomic_u8_new))] -#![cfg_attr(not(stage0), feature(const_atomic_i16_new))] -#![cfg_attr(not(stage0), feature(const_atomic_u16_new))] -#![cfg_attr(not(stage0), feature(const_atomic_i32_new))] -#![cfg_attr(not(stage0), feature(const_atomic_u32_new))] -#![cfg_attr(not(stage0), feature(const_atomic_i64_new))] -#![cfg_attr(not(stage0), feature(const_atomic_u64_new))] -#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))] -#![cfg_attr(not(stage0), feature(const_cell_new))] -#![cfg_attr(not(stage0), feature(const_nonzero_new))] +#![feature(doc_spotlight)] #[prelude_import] #[allow(unused)] @@ -190,3 +173,4 @@ pub mod fmt; mod char_private; mod iter_private; mod tuple; +mod unit; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d64c984ea7d..6e3dbcbec9d 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -120,6 +120,9 @@ macro_rules! assert_eq { } } }); + ($left:expr, $right:expr,) => ({ + assert_eq!($left, $right) + }); ($left:expr, $right:expr, $($arg:tt)+) => ({ match (&($left), &($right)) { (left_val, right_val) => { @@ -168,6 +171,9 @@ macro_rules! assert_ne { } } }); + ($left:expr, $right:expr,) => { + assert_ne!($left, $right) + }; ($left:expr, $right:expr, $($arg:tt)+) => ({ match (&($left), &($right)) { (left_val, right_val) => { @@ -355,7 +361,7 @@ macro_rules! try { }) } -/// Write formatted data into a buffer +/// Write formatted data into a buffer. /// /// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be /// formatted according to the specified format string and the result will be passed to the writer. @@ -606,9 +612,10 @@ mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] #[cfg(dox)] - macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({ - /* compiler built-in */ - }) } + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); + } /// Inspect an environment variable at compile time. /// @@ -618,7 +625,10 @@ mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] #[cfg(dox)] - macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) } + macro_rules! env { + ($name:expr) => ({ /* compiler built-in */ }); + ($name:expr,) => ({ /* compiler built-in */ }); + } /// Optionally inspect an environment variable at compile time. /// @@ -639,7 +649,8 @@ mod builtin { #[macro_export] #[cfg(dox)] macro_rules! concat_idents { - ($($e:ident),*) => ({ /* compiler built-in */ }) + ($($e:ident),*) => ({ /* compiler built-in */ }); + ($($e:ident,)*) => ({ /* compiler built-in */ }); } /// Concatenates literals into a static string slice. @@ -650,7 +661,10 @@ mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] #[cfg(dox)] - macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) } + macro_rules! concat { + ($($e:expr),*) => ({ /* compiler built-in */ }); + ($($e:expr,)*) => ({ /* compiler built-in */ }); + } /// A macro which expands to the line number on which it was invoked. /// @@ -682,7 +696,7 @@ mod builtin { #[cfg(dox)] macro_rules! file { () => ({ /* compiler built-in */ }) } - /// A macro which stringifies its argument. + /// A macro which stringifies its arguments. /// /// For more information, see the documentation for [`std::stringify!`]. /// @@ -690,7 +704,7 @@ mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] #[cfg(dox)] - macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } + macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) } /// Includes a utf8-encoded file as a string. /// diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index e8fd729b638..17e77654cf5 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -39,13 +39,14 @@ use hash::Hasher; /// [arc]: ../../std/sync/struct.Arc.html /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] -#[lang = "send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] pub unsafe trait Send { // empty. } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(unknown_lints)] +#[allow(auto_impl)] unsafe impl Send for .. { } #[stable(feature = "rust1", since = "1.0.0")] @@ -122,7 +123,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. } @@ -312,7 +313,7 @@ pub trait Copy : Clone { /// /// For cases when one does need thread-safe interior mutability, /// Rust provides [atomic data types], as well as explicit locking via -/// [`sync::Mutex`][mutex] and [`sync::RWLock`][rwlock]. These types +/// [`sync::Mutex`][mutex] and [`sync::RwLock`][rwlock]. These types /// ensure that any mutation cannot cause data races, hence the types /// are `Sync`. Likewise, [`sync::Arc`][arc] provides a thread-safe /// analogue of [`Rc`][rc]. @@ -349,6 +350,8 @@ pub unsafe trait Sync { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(unknown_lints)] +#[allow(auto_impl)] unsafe impl Sync for .. { } #[stable(feature = "rust1", since = "1.0.0")] @@ -562,6 +565,8 @@ mod impls { #[lang = "freeze"] unsafe trait Freeze {} +#[allow(unknown_lints)] +#[allow(auto_impl)] unsafe impl Freeze for .. {} impl<T: ?Sized> !Freeze for UnsafeCell<T> {} diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 669b93120cf..5b1a9399c39 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -209,6 +209,35 @@ pub fn forget<T>(t: T) { /// 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`. /// +/// # Size of `#[repr(C)]` items +/// +/// The `C` representation for items has a defined layout. With this layout, +/// the size of items is also stable as long as all fields have a stable size. +/// +/// ## Size of Structs +/// +/// For `structs`, the size is determined by the following algorithm. +/// +/// For each field in the struct ordered by declaration order: +/// +/// 1. Add the size of the field. +/// 2. Round up the current size to the nearest multiple of the next field's [alignment]. +/// +/// Finally, round the size of the struct to the nearest multiple of its [alignment]. +/// +/// Unlike `C`, zero sized structs are not rounded up to one byte in size. +/// +/// ## Size of Enums +/// +/// Enums that carry no data other than the descriminant have the same size as C enums +/// on the platform they are compiled for. +/// +/// ## Size of Unions +/// +/// The size of a union is the size of its largest field. +/// +/// Unlike `C`, zero sized unions are not rounded up to one byte in size. +/// /// # Examples /// /// ``` @@ -231,9 +260,57 @@ pub fn forget<T>(t: T) { /// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>()); /// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>()); /// ``` +/// +/// Using `#[repr(C)]`. +/// +/// ``` +/// use std::mem; +/// +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// // The size of the first field is 1, so add 1 to the size. Size is 1. +/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2. +/// // The size of the second field is 2, so add 2 to the size. Size is 4. +/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. +/// // The size of the third field is 1, so add 1 to the size. Size is 5. +/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6. +/// assert_eq!(6, mem::size_of::<FieldStruct>()); +/// +/// #[repr(C)] +/// struct TupleStruct(u8, u16, u8); +/// +/// // Tuple structs follow the same rules. +/// assert_eq!(6, mem::size_of::<TupleStruct>()); +/// +/// // Note that reordering the fields can lower the size. We can remove both padding bytes +/// // by putting `third` before `second`. +/// #[repr(C)] +/// struct FieldStructOptimized { +/// first: u8, +/// third: u8, +/// second: u16 +/// } +/// +/// assert_eq!(4, mem::size_of::<FieldStructOptimized>()); +/// +/// // Union size is the size of the largest field. +/// #[repr(C)] +/// union ExampleUnion { +/// smaller: u8, +/// larger: u16 +/// } +/// +/// assert_eq!(2, mem::size_of::<ExampleUnion>()); +/// ``` +/// +/// [alignment]: ./fn.align_of.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_size_of"))] pub const fn size_of<T>() -> usize { unsafe { intrinsics::size_of::<T>() } } @@ -325,7 +402,6 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_align_of"))] pub const fn align_of<T>() -> usize { unsafe { intrinsics::min_align_of::<T>() } } @@ -351,9 +427,11 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize { /// Returns whether dropping values of type `T` matters. /// -/// This is purely an optimization hint, and may be implemented conservatively. -/// For instance, always returning `true` would be a valid implementation of -/// this function. +/// This is purely an optimization hint, and may be implemented conservatively: +/// it may return `true` for types that don't actually need to be dropped. +/// As such always returning `true` would be a valid implementation of +/// this function. However if this function actually returns `false`, then you +/// can be certain dropping `T` has no side effect. /// /// Low level implementations of things like collections, which need to manually /// drop their data, should use this function to avoid unnecessarily @@ -402,7 +480,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>() } } @@ -758,7 +836,7 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U { /// /// See the `discriminant` function in this module for more information. #[stable(feature = "discriminant_value", since = "1.21.0")] -pub struct Discriminant<T>(u64, PhantomData<*const T>); +pub struct Discriminant<T>(u64, PhantomData<fn() -> T>); // N.B. These trait implementations cannot be derived because we don't want any bounds on T. diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index f075d825f5d..2c966eb3b57 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -28,8 +28,7 @@ macro_rules! impl_zeroable_for_pointer_types { unsafe impl<T: ?Sized> Zeroable for $Ptr { #[inline] fn is_zero(&self) -> bool { - // Cast because `is_null` is only available on thin pointers - (*self as *mut u8).is_null() + (*self).is_null() } } )+ @@ -71,7 +70,6 @@ impl<T: Zeroable> NonZero<T> { #[unstable(feature = "nonzero", reason = "needs an RFC to flesh out the design", issue = "27730")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_nonzero_new"))] #[inline] pub const unsafe fn new_unchecked(inner: T) -> Self { NonZero(inner) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index bf31deae7a6..7c7562eac51 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -12,9 +12,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -use convert::TryFrom; +use convert::{Infallible, TryFrom}; use fmt; use intrinsics; +use ops; use str::FromStr; /// Provides intentionally-wrapped arithmetic on `T`. @@ -109,7 +110,6 @@ macro_rules! int_impl { /// assert_eq!(i8::min_value(), -128); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_min_value"))] #[inline] pub const fn min_value() -> Self { !0 ^ ((!0 as $UnsignedT) >> 1) as Self @@ -123,7 +123,6 @@ macro_rules! int_impl { /// assert_eq!(i8::max_value(), 127); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_max_value"))] #[inline] pub const fn max_value() -> Self { !Self::min_value() @@ -131,7 +130,14 @@ macro_rules! int_impl { /// Converts a string slice in a given base to an integer. /// + /// The string is expected to be an optional `+` or `-` sign + /// followed by digits. /// Leading and trailing whitespace represent an error. + /// Digits are a subset of these characters, depending on `radix`: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` /// /// # Panics /// @@ -374,7 +380,7 @@ macro_rules! int_impl { if cfg!(target_endian = "little") { self } else { self.swap_bytes() } } - /// Checked integer addition. Computes `self + other`, returning `None` + /// Checked integer addition. Computes `self + rhs`, returning `None` /// if overflow occurred. /// /// # Examples @@ -387,12 +393,12 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_add(self, other: Self) -> Option<Self> { - let (a, b) = self.overflowing_add(other); + pub fn checked_add(self, rhs: Self) -> Option<Self> { + let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } - /// Checked integer subtraction. Computes `self - other`, returning + /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if underflow occurred. /// /// # Examples @@ -405,12 +411,12 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_sub(self, other: Self) -> Option<Self> { - let (a, b) = self.overflowing_sub(other); + pub fn checked_sub(self, rhs: Self) -> Option<Self> { + let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } - /// Checked integer multiplication. Computes `self * other`, returning + /// Checked integer multiplication. Computes `self * rhs`, returning /// `None` if underflow or overflow occurred. /// /// # Examples @@ -423,13 +429,13 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_mul(self, other: Self) -> Option<Self> { - let (a, b) = self.overflowing_mul(other); + pub fn checked_mul(self, rhs: Self) -> Option<Self> { + let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } - /// Checked integer division. Computes `self / other`, returning `None` - /// if `other == 0` or the operation results in underflow or overflow. + /// Checked integer division. Computes `self / rhs`, returning `None` + /// if `rhs == 0` or the operation results in underflow or overflow. /// /// # Examples /// @@ -442,16 +448,16 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_div(self, other: Self) -> Option<Self> { - if other == 0 || (self == Self::min_value() && other == -1) { + pub fn checked_div(self, rhs: Self) -> Option<Self> { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(unsafe { intrinsics::unchecked_div(self, other) }) + Some(unsafe { intrinsics::unchecked_div(self, rhs) }) } } - /// Checked integer remainder. Computes `self % other`, returning `None` - /// if `other == 0` or the operation results in underflow or overflow. + /// Checked integer remainder. Computes `self % rhs`, returning `None` + /// if `rhs == 0` or the operation results in underflow or overflow. /// /// # Examples /// @@ -466,11 +472,11 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[inline] - pub fn checked_rem(self, other: Self) -> Option<Self> { - if other == 0 || (self == Self::min_value() && other == -1) { + pub fn checked_rem(self, rhs: Self) -> Option<Self> { + if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(unsafe { intrinsics::unchecked_rem(self, other) }) + Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) } } @@ -553,7 +559,7 @@ macro_rules! int_impl { } } - /// Saturating integer addition. Computes `self + other`, saturating at + /// Saturating integer addition. Computes `self + rhs`, saturating at /// the numeric bounds instead of overflowing. /// /// # Examples @@ -566,15 +572,15 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn saturating_add(self, other: Self) -> Self { - match self.checked_add(other) { + pub fn saturating_add(self, rhs: Self) -> Self { + match self.checked_add(rhs) { Some(x) => x, - None if other >= 0 => Self::max_value(), + None if rhs >= 0 => Self::max_value(), None => Self::min_value(), } } - /// Saturating integer subtraction. Computes `self - other`, saturating + /// Saturating integer subtraction. Computes `self - rhs`, saturating /// at the numeric bounds instead of overflowing. /// /// # Examples @@ -587,15 +593,15 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn saturating_sub(self, other: Self) -> Self { - match self.checked_sub(other) { + pub fn saturating_sub(self, rhs: Self) -> Self { + match self.checked_sub(rhs) { Some(x) => x, - None if other >= 0 => Self::min_value(), + None if rhs >= 0 => Self::min_value(), None => Self::max_value(), } } - /// Saturating integer multiplication. Computes `self * other`, + /// Saturating integer multiplication. Computes `self * rhs`, /// saturating at the numeric bounds instead of overflowing. /// /// # Examples @@ -611,9 +617,9 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[inline] - pub fn saturating_mul(self, other: Self) -> Self { - self.checked_mul(other).unwrap_or_else(|| { - if (self < 0 && other < 0) || (self > 0 && other > 0) { + pub fn saturating_mul(self, rhs: Self) -> Self { + self.checked_mul(rhs).unwrap_or_else(|| { + if (self < 0 && rhs < 0) || (self > 0 && rhs > 0) { Self::max_value() } else { Self::min_value() @@ -621,7 +627,7 @@ macro_rules! int_impl { }) } - /// Wrapping (modular) addition. Computes `self + other`, + /// Wrapping (modular) addition. Computes `self + rhs`, /// wrapping around at the boundary of the type. /// /// # Examples @@ -640,7 +646,7 @@ macro_rules! int_impl { } } - /// Wrapping (modular) subtraction. Computes `self - other`, + /// Wrapping (modular) subtraction. Computes `self - rhs`, /// wrapping around at the boundary of the type. /// /// # Examples @@ -660,7 +666,7 @@ macro_rules! int_impl { } /// Wrapping (modular) multiplication. Computes `self * - /// other`, wrapping around at the boundary of the type. + /// rhs`, wrapping around at the boundary of the type. /// /// # Examples /// @@ -678,7 +684,7 @@ macro_rules! int_impl { } } - /// Wrapping (modular) division. Computes `self / other`, + /// Wrapping (modular) division. Computes `self / rhs`, /// wrapping around at the boundary of the type. /// /// The only case where such wrapping can occur is when one @@ -706,7 +712,7 @@ macro_rules! int_impl { self.overflowing_div(rhs).0 } - /// Wrapping (modular) remainder. Computes `self % other`, + /// Wrapping (modular) remainder. Computes `self % rhs`, /// wrapping around at the boundary of the type. /// /// Such wrap-around never actually occurs mathematically; @@ -1282,7 +1288,6 @@ macro_rules! uint_impl { /// assert_eq!(u8::min_value(), 0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_min_value"))] #[inline] pub const fn min_value() -> Self { 0 } @@ -1294,13 +1299,23 @@ macro_rules! uint_impl { /// assert_eq!(u8::max_value(), 255); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_max_value"))] #[inline] pub const fn max_value() -> Self { !0 } /// Converts a string slice in a given base to an integer. /// + /// The string is expected to be an optional `+` sign + /// followed by digits. /// Leading and trailing whitespace represent an error. + /// Digits are a subset of these characters, depending on `radix`: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// + /// This function panics if `radix` is not in the range from 2 to 36. /// /// # Examples /// @@ -1558,7 +1573,7 @@ macro_rules! uint_impl { if cfg!(target_endian = "little") { self } else { self.swap_bytes() } } - /// Checked integer addition. Computes `self + other`, returning `None` + /// Checked integer addition. Computes `self + rhs`, returning `None` /// if overflow occurred. /// /// # Examples @@ -1571,12 +1586,12 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_add(self, other: Self) -> Option<Self> { - let (a, b) = self.overflowing_add(other); + pub fn checked_add(self, rhs: Self) -> Option<Self> { + let (a, b) = self.overflowing_add(rhs); if b {None} else {Some(a)} } - /// Checked integer subtraction. Computes `self - other`, returning + /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if underflow occurred. /// /// # Examples @@ -1589,12 +1604,12 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_sub(self, other: Self) -> Option<Self> { - let (a, b) = self.overflowing_sub(other); + pub fn checked_sub(self, rhs: Self) -> Option<Self> { + let (a, b) = self.overflowing_sub(rhs); if b {None} else {Some(a)} } - /// Checked integer multiplication. Computes `self * other`, returning + /// Checked integer multiplication. Computes `self * rhs`, returning /// `None` if underflow or overflow occurred. /// /// # Examples @@ -1607,13 +1622,13 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_mul(self, other: Self) -> Option<Self> { - let (a, b) = self.overflowing_mul(other); + pub fn checked_mul(self, rhs: Self) -> Option<Self> { + let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } - /// Checked integer division. Computes `self / other`, returning `None` - /// if `other == 0` or the operation results in underflow or overflow. + /// Checked integer division. Computes `self / rhs`, returning `None` + /// if `rhs == 0` or the operation results in underflow or overflow. /// /// # Examples /// @@ -1625,15 +1640,15 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn checked_div(self, other: Self) -> Option<Self> { - match other { + pub fn checked_div(self, rhs: Self) -> Option<Self> { + match rhs { 0 => None, - other => Some(unsafe { intrinsics::unchecked_div(self, other) }), + rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }), } } - /// Checked integer remainder. Computes `self % other`, returning `None` - /// if `other == 0` or the operation results in underflow or overflow. + /// Checked integer remainder. Computes `self % rhs`, returning `None` + /// if `rhs == 0` or the operation results in underflow or overflow. /// /// # Examples /// @@ -1645,11 +1660,11 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[inline] - pub fn checked_rem(self, other: Self) -> Option<Self> { - if other == 0 { + pub fn checked_rem(self, rhs: Self) -> Option<Self> { + if rhs == 0 { None } else { - Some(unsafe { intrinsics::unchecked_rem(self, other) }) + Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) } } @@ -1709,7 +1724,7 @@ macro_rules! uint_impl { if b {None} else {Some(a)} } - /// Saturating integer addition. Computes `self + other`, saturating at + /// Saturating integer addition. Computes `self + rhs`, saturating at /// the numeric bounds instead of overflowing. /// /// # Examples @@ -1722,14 +1737,14 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn saturating_add(self, other: Self) -> Self { - match self.checked_add(other) { + pub fn saturating_add(self, rhs: Self) -> Self { + match self.checked_add(rhs) { Some(x) => x, None => Self::max_value(), } } - /// Saturating integer subtraction. Computes `self - other`, saturating + /// Saturating integer subtraction. Computes `self - rhs`, saturating /// at the numeric bounds instead of overflowing. /// /// # Examples @@ -1742,14 +1757,14 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn saturating_sub(self, other: Self) -> Self { - match self.checked_sub(other) { + pub fn saturating_sub(self, rhs: Self) -> Self { + match self.checked_sub(rhs) { Some(x) => x, None => Self::min_value(), } } - /// Saturating integer multiplication. Computes `self * other`, + /// Saturating integer multiplication. Computes `self * rhs`, /// saturating at the numeric bounds instead of overflowing. /// /// # Examples @@ -1764,11 +1779,11 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[inline] - pub fn saturating_mul(self, other: Self) -> Self { - self.checked_mul(other).unwrap_or(Self::max_value()) + pub fn saturating_mul(self, rhs: Self) -> Self { + self.checked_mul(rhs).unwrap_or(Self::max_value()) } - /// Wrapping (modular) addition. Computes `self + other`, + /// Wrapping (modular) addition. Computes `self + rhs`, /// wrapping around at the boundary of the type. /// /// # Examples @@ -1787,7 +1802,7 @@ macro_rules! uint_impl { } } - /// Wrapping (modular) subtraction. Computes `self - other`, + /// Wrapping (modular) subtraction. Computes `self - rhs`, /// wrapping around at the boundary of the type. /// /// # Examples @@ -1807,7 +1822,7 @@ macro_rules! uint_impl { } /// Wrapping (modular) multiplication. Computes `self * - /// other`, wrapping around at the boundary of the type. + /// rhs`, wrapping around at the boundary of the type. /// /// # Examples /// @@ -1825,7 +1840,7 @@ macro_rules! uint_impl { } } - /// Wrapping (modular) division. Computes `self / other`. + /// Wrapping (modular) division. Computes `self / rhs`. /// Wrapped division on unsigned types is just normal division. /// There's no way wrapping could ever happen. /// This function exists, so that all operations @@ -1844,7 +1859,7 @@ macro_rules! uint_impl { self / rhs } - /// Wrapping (modular) remainder. Computes `self % other`. + /// Wrapping (modular) remainder. Computes `self % rhs`. /// Wrapped remainder calculation on unsigned types is /// just the regular remainder calculation. /// There's no way wrapping could ever happen. @@ -2223,7 +2238,8 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn next_power_of_two(self) -> Self { - self.one_less_than_next_power_of_two() + 1 + // Call the trait to get overflow checks + ops::Add::add(self.one_less_than_next_power_of_two(), 1) } /// Returns the smallest power of two greater than or equal to `n`. If @@ -2257,6 +2273,547 @@ impl u8 { intrinsics::add_with_overflow, intrinsics::sub_with_overflow, intrinsics::mul_with_overflow } + + + /// Checks if the value is within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// let ascii = 97u8; + /// let non_ascii = 150u8; + /// + /// assert!(ascii.is_ascii()); + /// assert!(!non_ascii.is_ascii()); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")] + #[inline] + pub fn is_ascii(&self) -> bool { + *self & 128 == 0 + } + + /// Makes a copy of the value in its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// let lowercase_a = 97u8; + /// + /// assert_eq!(65, lowercase_a.to_ascii_uppercase()); + /// ``` + /// + /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")] + #[inline] + pub fn to_ascii_uppercase(&self) -> u8 { + ASCII_UPPERCASE_MAP[*self as usize] + } + + /// Makes a copy of the value in its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 65u8; + /// + /// assert_eq!(97, uppercase_a.to_ascii_lowercase()); + /// ``` + /// + /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")] + #[inline] + pub fn to_ascii_lowercase(&self) -> u8 { + ASCII_LOWERCASE_MAP[*self as usize] + } + + /// Checks that two values are an ASCII case-insensitive match. + /// + /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`. + /// + /// # Examples + /// + /// ``` + /// let lowercase_a = 97u8; + /// let uppercase_a = 65u8; + /// + /// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a)); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")] + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &u8) -> bool { + self.to_ascii_lowercase() == other.to_ascii_lowercase() + } + + /// Converts this value to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// let mut byte = b'a'; + /// + /// byte.make_ascii_uppercase(); + /// + /// assert_eq!(b'A', byte); + /// ``` + /// + /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")] + #[inline] + pub fn make_ascii_uppercase(&mut self) { + *self = self.to_ascii_uppercase(); + } + + /// Converts this value to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// let mut byte = b'A'; + /// + /// byte.make_ascii_lowercase(); + /// + /// assert_eq!(b'a', byte); + /// ``` + /// + /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")] + #[inline] + pub fn make_ascii_lowercase(&mut self) { + *self = self.to_ascii_lowercase(); + } + + /// Checks if the value is an ASCII alphabetic character: + /// + /// - U+0041 'A' ... U+005A 'Z', or + /// - U+0061 'a' ... U+007A 'z'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(uppercase_a.is_ascii_alphabetic()); + /// assert!(uppercase_g.is_ascii_alphabetic()); + /// assert!(a.is_ascii_alphabetic()); + /// assert!(g.is_ascii_alphabetic()); + /// assert!(!zero.is_ascii_alphabetic()); + /// assert!(!percent.is_ascii_alphabetic()); + /// assert!(!space.is_ascii_alphabetic()); + /// assert!(!lf.is_ascii_alphabetic()); + /// assert!(!esc.is_ascii_alphabetic()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_alphabetic(&self) -> bool { + if *self >= 0x80 { return false; } + match ASCII_CHARACTER_CLASS[*self as usize] { + L | Lx | U | Ux => true, + _ => false + } + } + + /// Checks if the value is an ASCII uppercase character: + /// U+0041 'A' ... U+005A 'Z'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(uppercase_a.is_ascii_uppercase()); + /// assert!(uppercase_g.is_ascii_uppercase()); + /// assert!(!a.is_ascii_uppercase()); + /// assert!(!g.is_ascii_uppercase()); + /// assert!(!zero.is_ascii_uppercase()); + /// assert!(!percent.is_ascii_uppercase()); + /// assert!(!space.is_ascii_uppercase()); + /// assert!(!lf.is_ascii_uppercase()); + /// assert!(!esc.is_ascii_uppercase()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_uppercase(&self) -> bool { + if *self >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[*self as usize] { + U | Ux => true, + _ => false + } + } + + /// Checks if the value is an ASCII lowercase character: + /// U+0061 'a' ... U+007A 'z'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(!uppercase_a.is_ascii_lowercase()); + /// assert!(!uppercase_g.is_ascii_lowercase()); + /// assert!(a.is_ascii_lowercase()); + /// assert!(g.is_ascii_lowercase()); + /// assert!(!zero.is_ascii_lowercase()); + /// assert!(!percent.is_ascii_lowercase()); + /// assert!(!space.is_ascii_lowercase()); + /// assert!(!lf.is_ascii_lowercase()); + /// assert!(!esc.is_ascii_lowercase()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_lowercase(&self) -> bool { + if *self >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[*self as usize] { + L | Lx => true, + _ => false + } + } + + /// Checks if the value is an ASCII alphanumeric character: + /// + /// - U+0041 'A' ... U+005A 'Z', or + /// - U+0061 'a' ... U+007A 'z', or + /// - U+0030 '0' ... U+0039 '9'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(uppercase_a.is_ascii_alphanumeric()); + /// assert!(uppercase_g.is_ascii_alphanumeric()); + /// assert!(a.is_ascii_alphanumeric()); + /// assert!(g.is_ascii_alphanumeric()); + /// assert!(zero.is_ascii_alphanumeric()); + /// assert!(!percent.is_ascii_alphanumeric()); + /// assert!(!space.is_ascii_alphanumeric()); + /// assert!(!lf.is_ascii_alphanumeric()); + /// assert!(!esc.is_ascii_alphanumeric()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_alphanumeric(&self) -> bool { + if *self >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[*self as usize] { + D | L | Lx | U | Ux => true, + _ => false + } + } + + /// Checks if the value is an ASCII decimal digit: + /// U+0030 '0' ... U+0039 '9'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(!uppercase_a.is_ascii_digit()); + /// assert!(!uppercase_g.is_ascii_digit()); + /// assert!(!a.is_ascii_digit()); + /// assert!(!g.is_ascii_digit()); + /// assert!(zero.is_ascii_digit()); + /// assert!(!percent.is_ascii_digit()); + /// assert!(!space.is_ascii_digit()); + /// assert!(!lf.is_ascii_digit()); + /// assert!(!esc.is_ascii_digit()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_digit(&self) -> bool { + if *self >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[*self as usize] { + D => true, + _ => false + } + } + + /// Checks if the value is an ASCII hexadecimal digit: + /// + /// - U+0030 '0' ... U+0039 '9', or + /// - U+0041 'A' ... U+0046 'F', or + /// - U+0061 'a' ... U+0066 'f'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(uppercase_a.is_ascii_hexdigit()); + /// assert!(!uppercase_g.is_ascii_hexdigit()); + /// assert!(a.is_ascii_hexdigit()); + /// assert!(!g.is_ascii_hexdigit()); + /// assert!(zero.is_ascii_hexdigit()); + /// assert!(!percent.is_ascii_hexdigit()); + /// assert!(!space.is_ascii_hexdigit()); + /// assert!(!lf.is_ascii_hexdigit()); + /// assert!(!esc.is_ascii_hexdigit()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_hexdigit(&self) -> bool { + if *self >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[*self as usize] { + D | Lx | Ux => true, + _ => false + } + } + + /// Checks if the value is an ASCII punctuation character: + /// + /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or + /// - U+003A ... U+0040 `: ; < = > ? @`, or + /// - U+005B ... U+0060 ``[ \ ] ^ _ ` ``, or + /// - U+007B ... U+007E `{ | } ~` + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(!uppercase_a.is_ascii_punctuation()); + /// assert!(!uppercase_g.is_ascii_punctuation()); + /// assert!(!a.is_ascii_punctuation()); + /// assert!(!g.is_ascii_punctuation()); + /// assert!(!zero.is_ascii_punctuation()); + /// assert!(percent.is_ascii_punctuation()); + /// assert!(!space.is_ascii_punctuation()); + /// assert!(!lf.is_ascii_punctuation()); + /// assert!(!esc.is_ascii_punctuation()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_punctuation(&self) -> bool { + if *self >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[*self as usize] { + P => true, + _ => false + } + } + + /// Checks if the value is an ASCII graphic character: + /// U+0021 '@' ... U+007E '~'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(uppercase_a.is_ascii_graphic()); + /// assert!(uppercase_g.is_ascii_graphic()); + /// assert!(a.is_ascii_graphic()); + /// assert!(g.is_ascii_graphic()); + /// assert!(zero.is_ascii_graphic()); + /// assert!(percent.is_ascii_graphic()); + /// assert!(!space.is_ascii_graphic()); + /// assert!(!lf.is_ascii_graphic()); + /// assert!(!esc.is_ascii_graphic()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_graphic(&self) -> bool { + if *self >= 0x80 { return false; } + match ASCII_CHARACTER_CLASS[*self as usize] { + Ux | U | Lx | L | D | P => true, + _ => false + } + } + + /// Checks if the value is an ASCII whitespace character: + /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED, + /// U+000C FORM FEED, or U+000D CARRIAGE RETURN. + /// + /// Rust uses the WhatWG Infra Standard's [definition of ASCII + /// whitespace][infra-aw]. There are several other definitions in + /// wide use. For instance, [the POSIX locale][pct] includes + /// U+000B VERTICAL TAB as well as all the above characters, + /// but—from the very same specification—[the default rule for + /// "field splitting" in the Bourne shell][bfs] considers *only* + /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace. + /// + /// If you are writing a program that will process an existing + /// file format, check what that format's definition of whitespace is + /// before using this function. + /// + /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace + /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 + /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(!uppercase_a.is_ascii_whitespace()); + /// assert!(!uppercase_g.is_ascii_whitespace()); + /// assert!(!a.is_ascii_whitespace()); + /// assert!(!g.is_ascii_whitespace()); + /// assert!(!zero.is_ascii_whitespace()); + /// assert!(!percent.is_ascii_whitespace()); + /// assert!(space.is_ascii_whitespace()); + /// assert!(lf.is_ascii_whitespace()); + /// assert!(!esc.is_ascii_whitespace()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_whitespace(&self) -> bool { + if *self >= 0x80 { return false; } + match ASCII_CHARACTER_CLASS[*self as usize] { + Cw | W => true, + _ => false + } + } + + /// Checks if the value is an ASCII control character: + /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE. + /// Note that most ASCII whitespace characters are control + /// characters, but SPACE is not. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_ctype)] + /// + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = 0x1b_u8; + /// + /// assert!(!uppercase_a.is_ascii_control()); + /// assert!(!uppercase_g.is_ascii_control()); + /// assert!(!a.is_ascii_control()); + /// assert!(!g.is_ascii_control()); + /// assert!(!zero.is_ascii_control()); + /// assert!(!percent.is_ascii_control()); + /// assert!(!space.is_ascii_control()); + /// assert!(lf.is_ascii_control()); + /// assert!(esc.is_ascii_control()); + /// ``` + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[inline] + pub fn is_ascii_control(&self) -> bool { + if *self >= 0x80 { return false; } + match ASCII_CHARACTER_CLASS[*self as usize] { + C | Cw => true, + _ => false + } + } } #[lang = "u16"] @@ -2507,16 +3064,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 +3153,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 +3182,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 +3200,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 +3226,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 +3252,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); } @@ -2934,3 +3483,106 @@ impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" // Float -> Float impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } + +static ASCII_LOWERCASE_MAP: [u8; 256] = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'', + b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', + b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', + b'8', b'9', b':', b';', b'<', b'=', b'>', b'?', + b'@', + + b'a', b'b', b'c', b'd', b'e', b'f', b'g', + b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', + b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', + b'x', b'y', b'z', + + b'[', b'\\', b']', b'^', b'_', + b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g', + b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', + b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', + b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +static ASCII_UPPERCASE_MAP: [u8; 256] = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'', + b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', + b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', + b'8', b'9', b':', b';', b'<', b'=', b'>', b'?', + b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G', + b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', + b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', + b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_', + b'`', + + b'A', b'B', b'C', b'D', b'E', b'F', b'G', + b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', + b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', + b'X', b'Y', b'Z', + + b'{', b'|', b'}', b'~', 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +enum AsciiCharacterClass { + C, // control + Cw, // control whitespace + W, // whitespace + D, // digit + L, // lowercase + Lx, // lowercase hex digit + U, // uppercase + Ux, // uppercase hex digit + P, // punctuation +} +use self::AsciiCharacterClass::*; + +static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [ +// _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f + C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_ + C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_ + W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_ + D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_ + P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_ + U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_ + P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_ + L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_ +]; 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/deref.rs b/src/libcore/ops/deref.rs index ea8dd820878..80c48c7b28e 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -18,7 +18,7 @@ /// Implementing `Deref` for smart pointers makes accessing the data behind them /// convenient, which is why they implement `Deref`. On the other hand, the /// rules regarding `Deref` and [`DerefMut`] were designed specifically to -/// accomodate smart pointers. Because of this, **`Deref` should only be +/// accommodate smart pointers. Because of this, **`Deref` should only be /// implemented for smart pointers** to avoid confusion. /// /// For similar reasons, **this trait should never fail**. Failure during @@ -40,7 +40,7 @@ /// [book]: ../../book/second-edition/ch15-02-deref.html /// [`DerefMut`]: trait.DerefMut.html /// [more]: #more-on-deref-coercion -/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [ref-deref-trait]: ../../reference/the-deref-trait.html /// [type coercions]: ../../reference/type-coercions.html /// @@ -103,7 +103,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// Implementing `DerefMut` for smart pointers makes mutating the data behind /// them convenient, which is why they implement `DerefMut`. On the other hand, /// the rules regarding [`Deref`] and `DerefMut` were designed specifically to -/// accomodate smart pointers. Because of this, **`DerefMut` should only be +/// accommodate smart pointers. Because of this, **`DerefMut` should only be /// implemented for smart pointers** to avoid confusion. /// /// For similar reasons, **this trait should never fail**. Failure during @@ -127,7 +127,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// [book]: ../../book/second-edition/ch15-02-deref.html /// [`Deref`]: trait.Deref.html /// [more]: #more-on-deref-coercion -/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [ref-deref-trait]: ../../reference/the-deref-trait.html /// [type coercions]: ../../reference/type-coercions.html /// diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs index 798c182bc6e..dc7669d195c 100644 --- a/src/libcore/ops/generator.rs +++ b/src/libcore/ops/generator.rs @@ -14,7 +14,7 @@ /// possible return values of a generator. Currently this corresponds to either /// a suspension point (`Yielded`) or a termination point (`Complete`). #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -#[cfg_attr(not(stage0), lang = "generator_state")] +#[lang = "generator_state"] #[unstable(feature = "generator_trait", issue = "43122")] pub enum GeneratorState<Y, R> { /// The generator suspended with a value. @@ -70,7 +70,7 @@ pub enum GeneratorState<Y, R> { /// More documentation of generators can be found in the unstable book. /// /// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 -#[cfg_attr(not(stage0), lang = "generator")] +#[lang = "generator"] #[unstable(feature = "generator_trait", issue = "43122")] #[fundamental] pub trait Generator { diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 8975b680ca7..70ef4487334 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -150,7 +150,7 @@ //! [`Sub`]: trait.Sub.html //! [`Mul`]: trait.Mul.html //! [`clone`]: ../clone/trait.Clone.html#tymethod.clone -//! [operator precedence]: ../../reference/expressions.html#operator-precedence +//! [operator precedence]: ../../reference/expressions.html#expression-precedence #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index e788b66a1ec..81e5cb5c350 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -15,24 +15,19 @@ /// extracting those success or failure values from an existing instance and /// creating a new instance from a success or failure value. #[unstable(feature = "try_trait", issue = "42327")] -#[cfg_attr(stage0, - rustc_on_unimplemented = "the `?` operator can only be used in a \ - function that returns `Result` \ - (or another type that implements `{Try}`)")] -#[cfg_attr(not(stage0), - rustc_on_unimplemented( - on(all( - any(from_method="from_error", from_method="from_ok"), - from_desugaring="?"), - message="the `?` operator can only be used in a \ - function that returns `Result` \ - (or another type that implements `{Try}`)", - label="cannot use the `?` operator in a function that returns `{Self}`"), - on(all(from_method="into_result", from_desugaring="?"), - message="the `?` operator can only be applied to values \ - that implement `{Try}`", - label="the `?` operator cannot be applied to type `{Self}`") -))] +#[rustc_on_unimplemented( + on(all( + any(from_method="from_error", from_method="from_ok"), + from_desugaring="?"), + message="the `?` operator can only be used in a \ + function that returns `Result` \ + (or another type that implements `{Try}`)", + label="cannot use the `?` operator in a function that returns `{Self}`"), + on(all(from_method="into_result", from_desugaring="?"), + message="the `?` operator can only be applied to values \ + that implement `{Try}`", + label="the `?` operator cannot be applied to type `{Self}`") +)] pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] 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..12e6e843056 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 @@ -607,6 +607,41 @@ impl<T> Option<T> { } } + /// Returns `None` if the option is `None`, otherwise calls `predicate` + /// with the wrapped value and returns: + /// + /// - `Some(t)` if `predicate` returns `true` (where `t` is the wrapped + /// value), and + /// - `None` if `predicate` returns `false`. + /// + /// This function works similar to `Iterator::filter()`. You can imagine + /// the `Option<T>` being an iterator over one or zero elements. `filter()` + /// lets you decide which elements to keep. + /// + /// # Examples + /// + /// ```rust + /// #![feature(option_filter)] + /// + /// fn is_even(n: &i32) -> bool { + /// n % 2 == 0 + /// } + /// + /// assert_eq!(None.filter(is_even), None); + /// assert_eq!(Some(3).filter(is_even), None); + /// assert_eq!(Some(4).filter(is_even), Some(4)); + /// ``` + #[inline] + #[unstable(feature = "option_filter", issue = "45860")] + pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self { + if let Some(x) = self { + if predicate(&x) { + return Some(x) + } + } + None + } + /// Returns the option if it contains a value, otherwise returns `optb`. /// /// # Examples @@ -1123,3 +1158,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..5e70c8283f4 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -27,8 +27,6 @@ use nonzero::NonZero; use cmp::Ordering::{self, Less, Equal, Greater}; -// FIXME #19649: intrinsic docs don't render, so these have no docs :( - #[stable(feature = "rust1", since = "1.0.0")] pub use intrinsics::copy_nonoverlapping; @@ -56,7 +54,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 @@ -76,7 +74,6 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_null"))] pub const fn null<T>() -> *const T { 0 as *const T } /// Creates a null mutable raw pointer. @@ -91,7 +88,6 @@ pub const fn null<T>() -> *const T { 0 as *const T } /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_null_mut"))] pub const fn null_mut<T>() -> *mut T { 0 as *mut T } /// Swaps the values at two mutable locations of the same type, without @@ -230,7 +226,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { /// moves the value out of `src` without preventing further usage of `src`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use +/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use /// because it will attempt to drop the value previously at `*src`. /// /// The pointer must be aligned; use `read_unaligned` if that is not the case. @@ -266,7 +262,7 @@ pub unsafe fn read<T>(src: *const T) -> T { /// moves the value out of `src` without preventing further usage of `src`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use +/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use /// because it will attempt to drop the value previously at `*src`. /// /// # Examples @@ -399,7 +395,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// moves the value out of `src` without preventing further usage of `src`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use +/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use /// because it will attempt to drop the value previously at `*src`. /// /// # Examples @@ -476,6 +472,11 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { impl<T: ?Sized> *const T { /// Returns `true` if the pointer is null. /// + /// Note that unsized types have many possible null pointers, as only the + /// raw data pointer is considered, not their length, vtable, etc. + /// Therefore, two pointers that are null may still not compare equal to + /// each other. + /// /// # Examples /// /// Basic usage: @@ -487,8 +488,10 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is_null(self) -> bool where T: Sized { - self == null() + pub fn is_null(self) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + (self as *const u8) == null() } /// Returns `None` if the pointer is null, or else returns a reference to @@ -519,7 +522,7 @@ impl<T: ?Sized> *const T { /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized { + pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { if self.is_null() { None } else { @@ -553,7 +556,7 @@ impl<T: ?Sized> *const T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -686,7 +689,7 @@ impl<T: ?Sized> *const T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -745,7 +748,7 @@ impl<T: ?Sized> *const T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -873,7 +876,7 @@ impl<T: ?Sized> *const T { /// moves the value out of `self` without preventing further usage of `self`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use + /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// /// The pointer must be aligned; use `read_unaligned` if that is not the case. @@ -927,7 +930,7 @@ impl<T: ?Sized> *const T { /// moves the value out of `self` without preventing further usage of `self`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use + /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// /// # Examples @@ -963,7 +966,7 @@ impl<T: ?Sized> *const T { /// moves the value out of `self` without preventing further usage of `self`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use + /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// /// # Examples @@ -1107,6 +1110,11 @@ impl<T: ?Sized> *const T { impl<T: ?Sized> *mut T { /// Returns `true` if the pointer is null. /// + /// Note that unsized types have many possible null pointers, as only the + /// raw data pointer is considered, not their length, vtable, etc. + /// Therefore, two pointers that are null may still not compare equal to + /// each other. + /// /// # Examples /// /// Basic usage: @@ -1118,8 +1126,10 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is_null(self) -> bool where T: Sized { - self == null_mut() + pub fn is_null(self) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + (self as *mut u8) == null_mut() } /// Returns `None` if the pointer is null, or else returns a reference to @@ -1150,7 +1160,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized { + pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { if self.is_null() { None } else { @@ -1184,7 +1194,7 @@ impl<T: ?Sized> *mut T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -1274,7 +1284,7 @@ impl<T: ?Sized> *mut T { /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized { + pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { if self.is_null() { None } else { @@ -1384,7 +1394,7 @@ impl<T: ?Sized> *mut T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -1443,7 +1453,7 @@ impl<T: ?Sized> *mut T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -1571,7 +1581,7 @@ impl<T: ?Sized> *mut T { /// moves the value out of `self` without preventing further usage of `self`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use + /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// /// The pointer must be aligned; use `read_unaligned` if that is not the case. @@ -1625,7 +1635,7 @@ impl<T: ?Sized> *mut T { /// moves the value out of `self` without preventing further usage of `self`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `src` is not used before the data is overwritten again (e.g. with `write`, - /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use + /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// /// # Examples @@ -1661,7 +1671,7 @@ impl<T: ?Sized> *mut T { /// moves the value out of `self` without preventing further usage of `self`. /// If `T` is not `Copy`, then care must be taken to ensure that the value at /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use + /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// /// # Examples @@ -2335,7 +2345,6 @@ impl<T: ?Sized> Unique<T> { /// /// `ptr` must be non-null. #[unstable(feature = "unique", issue = "27730")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_unique_new"))] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData } } @@ -2470,7 +2479,6 @@ impl<T: ?Sized> Shared<T> { /// /// `ptr` must be non-null. #[unstable(feature = "shared", issue = "27730")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_shared_new"))] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { Shared { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index ea064ca5c39..db5bffced10 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1060,7 +1060,7 @@ unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} /// [`Result`]: enum.Result.html /// [`into_iter`]: ../iter/trait.IntoIterator.html#tymethod.into_iter /// [`IntoIterator`]: ../iter/trait.IntoIterator.html -#[derive(Debug)] +#[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter<T> { inner: Option<T> } diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ae243f3f246..49c51f4f04f 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -16,9 +16,6 @@ #![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 @@ -43,7 +40,7 @@ use cmp; use fmt; use intrinsics::assume; use iter::*; -use ops::{FnMut, self}; +use ops::{FnMut, Try, self}; use option::Option; use option::Option::{None, Some}; use result::Result; @@ -394,23 +391,25 @@ impl<T> SliceExt for [T] { fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize> where F: FnMut(&'a T) -> Ordering { + let s = self; + let mut size = s.len(); + if size == 0 { + return Err(0); + } let mut base = 0usize; - let mut s = self; - - loop { - let (head, tail) = s.split_at(s.len() >> 1); - if tail.is_empty() { - return Err(base) - } - match f(&tail[0]) { - Less => { - base += head.len() + 1; - s = &tail[1..]; - } - Greater => s = head, - Equal => return Ok(base + head.len()), - } + while size > 1 { + let half = size / 2; + let mid = base + half; + // mid is always in [0, size). + // mid >= 0: by definition + // mid < size: mid = size / 2 + size / 4 + size / 8 ... + let cmp = f(unsafe { s.get_unchecked(mid) }); + base = if cmp == Greater { base } else { mid }; + size -= half; } + // base is always in [0, size) because base <= mid. + let cmp = f(unsafe { s.get_unchecked(base) }); + if cmp == Equal { Ok(base) } else { Err(base + (cmp == Less) as usize) } } #[inline] @@ -1047,32 +1046,32 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { #[inline] fn get(self, slice: &[T]) -> Option<&[T]> { - (RangeInclusive { start: 0, end: self.end }).get(slice) + (0..=self.end).get(slice) } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { - (RangeInclusive { start: 0, end: self.end }).get_mut(slice) + (0..=self.end).get_mut(slice) } #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (RangeInclusive { start: 0, end: self.end }).get_unchecked(slice) + (0..=self.end).get_unchecked(slice) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (RangeInclusive { start: 0, end: self.end }).get_unchecked_mut(slice) + (0..=self.end).get_unchecked_mut(slice) } #[inline] fn index(self, slice: &[T]) -> &[T] { - (RangeInclusive { start: 0, end: self.end }).index(slice) + (0..=self.end).index(slice) } #[inline] fn index_mut(self, slice: &mut [T]) -> &mut [T] { - (RangeInclusive { start: 0, end: self.end }).index_mut(slice) + (0..=self.end).index_mut(slice) } } @@ -1166,62 +1165,37 @@ macro_rules! iterator { self.next_back() } - fn all<F>(&mut self, mut predicate: F) -> bool - where F: FnMut(Self::Item) -> bool, - { - self.search_while(true, move |elt| { - if predicate(elt) { - SearchWhile::Continue - } else { - SearchWhile::Done(false) - } - }) - } - - fn any<F>(&mut self, mut predicate: F) -> bool - where F: FnMut(Self::Item) -> bool, - { - !self.all(move |elt| !predicate(elt)) - } - - fn find<F>(&mut self, mut predicate: F) -> Option<Self::Item> - where F: FnMut(&Self::Item) -> bool, + #[inline] + fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.search_while(None, move |elt| { - if predicate(&elt) { - SearchWhile::Done(Some(elt)) - } else { - SearchWhile::Continue + // manual unrolling is needed when there are conditional exits from the loop + let mut accum = init; + unsafe { + while ptrdistance(self.ptr, self.end) >= 4 { + accum = f(accum, $mkref!(self.ptr.post_inc()))?; + accum = f(accum, $mkref!(self.ptr.post_inc()))?; + accum = f(accum, $mkref!(self.ptr.post_inc()))?; + accum = f(accum, $mkref!(self.ptr.post_inc()))?; } - }) - } - - fn position<F>(&mut self, mut predicate: F) -> Option<usize> - where F: FnMut(Self::Item) -> bool, - { - let mut index = 0; - self.search_while(None, move |elt| { - if predicate(elt) { - SearchWhile::Done(Some(index)) - } else { - index += 1; - SearchWhile::Continue + while self.ptr != self.end { + accum = f(accum, $mkref!(self.ptr.post_inc()))?; } - }) + } + Try::from_ok(accum) } - fn rposition<F>(&mut self, mut predicate: F) -> Option<usize> - where F: FnMut(Self::Item) -> bool, + #[inline] + fn fold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut index = self.len(); - self.rsearch_while(None, move |elt| { - index -= 1; - if predicate(elt) { - SearchWhile::Done(Some(index)) - } else { - SearchWhile::Continue - } - }) + // Let LLVM unroll this, rather than using the default + // impl that would force the manual unrolling above + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x); + } + accum } } @@ -1243,59 +1217,37 @@ macro_rules! iterator { } } - fn rfind<F>(&mut self, mut predicate: F) -> Option<Self::Item> - where F: FnMut(&Self::Item) -> bool, - { - self.rsearch_while(None, move |elt| { - if predicate(&elt) { - SearchWhile::Done(Some(elt)) - } else { - SearchWhile::Continue - } - }) - } - - } - - // search_while is a generalization of the internal iteration methods. - impl<'a, T> $name<'a, T> { - // search through the iterator's element using the closure `g`. - // if no element was found, return `default`. - fn search_while<Acc, G>(&mut self, default: Acc, mut g: G) -> Acc - where Self: Sized, - G: FnMut($elem) -> SearchWhile<Acc> + #[inline] + fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { // manual unrolling is needed when there are conditional exits from the loop + let mut accum = init; unsafe { while ptrdistance(self.ptr, self.end) >= 4 { - search_while!(g($mkref!(self.ptr.post_inc()))); - search_while!(g($mkref!(self.ptr.post_inc()))); - search_while!(g($mkref!(self.ptr.post_inc()))); - search_while!(g($mkref!(self.ptr.post_inc()))); + accum = f(accum, $mkref!(self.end.pre_dec()))?; + accum = f(accum, $mkref!(self.end.pre_dec()))?; + accum = f(accum, $mkref!(self.end.pre_dec()))?; + accum = f(accum, $mkref!(self.end.pre_dec()))?; } while self.ptr != self.end { - search_while!(g($mkref!(self.ptr.post_inc()))); + accum = f(accum, $mkref!(self.end.pre_dec()))?; } } - default + Try::from_ok(accum) } - fn rsearch_while<Acc, G>(&mut self, default: Acc, mut g: G) -> Acc - where Self: Sized, - G: FnMut($elem) -> SearchWhile<Acc> + #[inline] + fn rfold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, { - unsafe { - while ptrdistance(self.ptr, self.end) >= 4 { - search_while!(g($mkref!(self.end.pre_dec()))); - search_while!(g($mkref!(self.end.pre_dec()))); - search_while!(g($mkref!(self.end.pre_dec()))); - search_while!(g($mkref!(self.end.pre_dec()))); - } - while self.ptr != self.end { - search_while!(g($mkref!(self.end.pre_dec()))); - } + // Let LLVM unroll this, rather than using the default + // impl that would force the manual unrolling above + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); } - default + accum } } } @@ -1329,24 +1281,6 @@ macro_rules! make_mut_slice { }} } -// An enum used for controlling the execution of `.search_while()`. -enum SearchWhile<T> { - // Continue searching - Continue, - // Fold is complete and will return this value - Done(T), -} - -// helper macro for search while's control flow -macro_rules! search_while { - ($e:expr) => { - match $e { - SearchWhile::Continue => { } - SearchWhile::Done(done) => return done, - } - } -} - /// Immutable slice iterator /// /// This struct is created by the [`iter`] method on [slices]. @@ -1654,7 +1588,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for Split<'a, T, P> where P: FnMut(&T } } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool { fn clone(&self) -> Split<'a, T, P> { @@ -2093,7 +2027,7 @@ pub struct Windows<'a, T:'a> { size: usize } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Windows<'a, T> { fn clone(&self) -> Windows<'a, T> { @@ -2195,7 +2129,7 @@ pub struct Chunks<'a, T:'a> { size: usize } -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Chunks<'a, T> { fn clone(&self) -> Chunks<'a, T> { @@ -2450,6 +2384,22 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { mem::transmute(Repr { data: p, len: len }) } +/// Converts a reference to T into a slice of length 1 (without copying). +#[unstable(feature = "from_ref", issue = "45703")] +pub fn from_ref<T>(s: &T) -> &[T] { + unsafe { + from_raw_parts(s, 1) + } +} + +/// Converts a reference to T into a slice of length 1 (without copying). +#[unstable(feature = "from_ref", issue = "45703")] +pub fn from_ref_mut<T>(s: &mut T) -> &mut [T] { + unsafe { + from_raw_parts_mut(s, 1) + } +} + // This function is public only because there is no other way to unit test heapsort. #[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "0")] #[doc(hidden)] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 62367b051fc..be5108238fc 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -18,7 +18,6 @@ use self::pattern::Pattern; use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use char; -use convert::TryFrom; use fmt; use iter::{Map, Cloned, FusedIterator, TrustedLen}; use iter_private::TrustedRandomAccess; @@ -77,9 +76,12 @@ pub trait FromStr: Sized { /// Parses a string `s` to return a value of this type. /// - /// If parsing succeeds, return the value inside `Ok`, otherwise + /// If parsing succeeds, return the value inside [`Ok`], otherwise /// when the string is ill-formatted return an error specific to the - /// inside `Err`. The error type is specific to implementation of the trait. + /// inside [`Err`]. The error type is specific to implementation of the trait. + /// + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// /// # Examples /// @@ -1407,16 +1409,6 @@ impl<'a> DoubleEndedIterator for LinesAny<'a> { impl<'a> FusedIterator for LinesAny<'a> {} /* -Section: Comparing strings -*/ - -/// Bytewise slice equality -#[inline] -fn eq_slice(a: &str, b: &str) -> bool { - a.as_bytes() == b.as_bytes() -} - -/* Section: UTF-8 validation */ @@ -1591,7 +1583,6 @@ mod traits { use cmp::Ordering; use ops; use slice::{self, SliceIndex}; - use str::eq_slice; /// Implements ordering of strings. /// @@ -1612,7 +1603,7 @@ mod traits { impl PartialEq for str { #[inline] fn eq(&self, other: &str) -> bool { - eq_slice(self, other) + self.as_bytes() == other.as_bytes() } #[inline] fn ne(&self, other: &str) -> bool { !(*self).eq(other) } @@ -2198,7 +2189,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` @@ -2518,9 +2509,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..4c6ff4d1bb4 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -103,9 +103,8 @@ use fmt; /// /// On some platforms this function may not do anything at all. #[inline] -#[unstable(feature = "hint_core_should_pause", issue = "41196")] -pub fn hint_core_should_pause() -{ +#[stable(feature = "spin_loop_hint", since = "1.24.0")] +pub fn spin_loop_hint() { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] unsafe { asm!("pause" ::: "memory" : "volatile"); @@ -119,7 +118,9 @@ pub fn hint_core_should_pause() /// A boolean type which can be safely shared between threads. /// -/// This type has the same in-memory representation as a `bool`. +/// This type has the same in-memory representation as a [`bool`]. +/// +/// [`bool`]: ../../../std/primitive.bool.html #[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] pub struct AtomicBool { @@ -241,16 +242,17 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_atomic_bool_new"))] pub const fn new(v: bool) -> AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } - /// Returns a mutable reference to the underlying `bool`. + /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// + /// [`bool`]: ../../../std/primitive.bool.html + /// /// # Examples /// /// ``` @@ -369,7 +371,7 @@ impl AtomicBool { unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } - /// Stores a value into the `bool` if the current value is the same as the `current` value. + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// The return value is always the previous value. If it is equal to `current`, then the value /// was updated. @@ -378,6 +380,7 @@ impl AtomicBool { /// ordering of this operation. /// /// [`Ordering`]: enum.Ordering.html + /// [`bool`]: ../../../std/primitive.bool.html /// /// # Examples /// @@ -401,7 +404,7 @@ impl AtomicBool { } } - /// Stores a value into the `bool` if the current value is the same as the `current` value. + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. @@ -412,6 +415,7 @@ impl AtomicBool { /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must /// be equivalent or weaker than the success ordering. /// + /// [`bool`]: ../../../std/primitive.bool.html /// [`Ordering`]: enum.Ordering.html /// [`Release`]: enum.Ordering.html#variant.Release /// [`AcqRel`]: enum.Ordering.html#variant.Release @@ -452,7 +456,7 @@ impl AtomicBool { } } - /// Stores a value into the `bool` if the current value is the same as the `current` value. + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The @@ -465,6 +469,7 @@ impl AtomicBool { /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or /// weaker than the success ordering. /// + /// [`bool`]: ../../../std/primitive.bool.html /// [`compare_exchange`]: #method.compare_exchange /// [`Ordering`]: enum.Ordering.html /// [`Release`]: enum.Ordering.html#variant.Release @@ -650,7 +655,6 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_atomic_ptr_new"))] pub const fn new(p: *mut T) -> AtomicPtr<T> { AtomicPtr { p: UnsafeCell::new(p) } } @@ -920,16 +924,44 @@ impl<T> AtomicPtr<T> { } } +#[cfg(target_has_atomic = "8")] +#[stable(feature = "atomic_bool_from", since = "1.24.0")] +impl From<bool> for AtomicBool { + #[inline] + fn from(b: bool) -> Self { Self::new(b) } +} + +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "atomic_from", since = "1.23.0")] +impl<T> From<*mut T> for AtomicPtr<T> { + #[inline] + fn from(p: *mut T) -> Self { Self::new(p) } +} + #[cfg(target_has_atomic = "ptr")] macro_rules! atomic_int { - ($stable:meta, $const_unstable:meta, + ($stable:meta, $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>, @@ -946,6 +978,12 @@ macro_rules! atomic_int { } } + #[stable(feature = "atomic_from", since = "1.23.0")] + impl From<$int_type> for $atomic_type { + #[inline] + fn from(v: $int_type) -> Self { Self::new(v) } + } + #[$stable_debug] impl fmt::Debug for $atomic_type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -971,7 +1009,6 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable] - #[cfg_attr(not(stage0), $const_unstable)] pub const fn new(v: $int_type) -> Self { $atomic_type {v: UnsafeCell::new(v)} } @@ -1335,91 +1372,91 @@ macro_rules! atomic_int { #[cfg(target_has_atomic = "8")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_i8_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_u8_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_i16_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_u16_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_i32_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_u32_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_i64_new"), 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")] atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), - rustc_const_unstable(feature = "const_atomic_u64_new"), 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")] atomic_int!{ stable(feature = "rust1", since = "1.0.0"), - rustc_const_unstable(feature = "const_atomic_isize_new"), 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")] atomic_int!{ stable(feature = "rust1", since = "1.0.0"), - rustc_const_unstable(feature = "const_atomic_usize_new"), 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 +1789,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/array.rs b/src/libcore/tests/array.rs index 6af031dee58..6278d5e23e0 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use core::array::FixedSizeArray; +use core::convert::TryFrom; #[test] fn fixed_size_array() { @@ -26,3 +27,25 @@ fn fixed_size_array() { assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0); assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); } + +#[test] +fn array_try_from() { + macro_rules! test { + ($($N:expr)+) => { + $({ + type Array = [u8; $N]; + let array: Array = [0; $N]; + let slice: &[u8] = &array[..]; + + let result = <&Array>::try_from(slice); + assert_eq!(&array, result.unwrap()); + })+ + } + } + test! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 + } +} 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/hash/mod.rs b/src/libcore/tests/hash/mod.rs index e8ea6044f5f..8716421b424 100644 --- a/src/libcore/tests/hash/mod.rs +++ b/src/libcore/tests/hash/mod.rs @@ -12,6 +12,7 @@ mod sip; use std::hash::{Hash, Hasher}; use std::default::Default; +use std::rc::Rc; struct MyHasher { hash: u64, @@ -64,18 +65,28 @@ fn test_writer_hasher() { assert_eq!(hash(& s), 97 + 0xFF); let s: Box<str> = String::from("a").into_boxed_str(); assert_eq!(hash(& s), 97 + 0xFF); + let s: Rc<&str> = Rc::new("a"); + assert_eq!(hash(&s), 97 + 0xFF); let cs: &[u8] = &[1, 2, 3]; assert_eq!(hash(& cs), 9); let cs: Box<[u8]> = Box::new([1, 2, 3]); assert_eq!(hash(& cs), 9); - - // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]> + let cs: Rc<[u8]> = Rc::new([1, 2, 3]); + assert_eq!(hash(& cs), 9); let ptr = 5_usize as *const i32; assert_eq!(hash(&ptr), 5); let ptr = 5_usize as *mut i32; assert_eq!(hash(&ptr), 5); + + let cs: &mut [u8] = &mut [1, 2, 3]; + let ptr = cs.as_ptr(); + let slice_ptr = cs as *const [u8]; + assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64); + + let slice_ptr = cs as *mut [u8]; + assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64); } struct Custom { hash: u64 } diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs index 4a9657e0340..c6dd41798f2 100644 --- a/src/libcore/tests/hash/sip.rs +++ b/src/libcore/tests/hash/sip.rs @@ -243,24 +243,22 @@ fn test_siphash_2_4() { t += 1; } } -#[test] #[cfg(target_arch = "arm")] + +#[test] +#[cfg(target_pointer_width = "32")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert!(hash(&(val as u64)) != hash(&(val as usize))); assert_eq!(hash(&(val as u32)), hash(&(val as usize))); } -#[test] #[cfg(target_arch = "x86_64")] + +#[test] +#[cfg(target_pointer_width = "64")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert_eq!(hash(&(val as u64)), hash(&(val as usize))); assert!(hash(&(val as u32)) != hash(&(val as usize))); } -#[test] #[cfg(target_arch = "x86")] -fn test_hash_usize() { - let val = 0xdeadbeef_deadbeef_u64; - assert!(hash(&(val as u64)) != hash(&(val as usize))); - assert_eq!(hash(&(val as u32)), hash(&(val as usize))); -} #[test] fn test_hash_idempotent() { diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3c4ea974fc9..5cac5b26d88 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,45 @@ 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()); + + let it = xs.iter().skip(5); + let i = it.rfold(ys.len(), |i, &x| { + let i = i - 1; + assert_eq!(x, ys[i]); + i + }); + assert_eq!(i, 0); + + let mut it = xs.iter().skip(5); + assert_eq!(it.next(), Some(&ys[0])); // process skips before folding + let i = it.rfold(ys.len(), |i, &x| { + let i = i - 1; + assert_eq!(x, ys[i]); + i + }); + assert_eq!(i, 1); + +} + +#[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 +794,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 +827,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(); @@ -1242,6 +1410,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)); @@ -1304,3 +1497,207 @@ fn test_step_replace_no_between() { assert_eq!(x, 1); assert_eq!(y, 5); } + +#[test] +fn test_rev_try_folds() { + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((1..10).rev().try_fold(7, f), (1..10).try_rfold(7, f)); + assert_eq!((1..10).rev().try_rfold(7, f), (1..10).try_fold(7, f)); + + let a = [10, 20, 30, 40, 100, 60, 70, 80, 90]; + let mut iter = a.iter().rev(); + assert_eq!(iter.try_fold(0_i8, |acc, &x| acc.checked_add(x)), None); + assert_eq!(iter.next(), Some(&70)); + let mut iter = a.iter().rev(); + assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None); + assert_eq!(iter.next_back(), Some(&60)); +} + +#[test] +fn test_cloned_try_folds() { + let a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let f = &|acc, x| i32::checked_add(2*acc, x); + let f_ref = &|acc, &x| i32::checked_add(2*acc, x); + assert_eq!(a.iter().cloned().try_fold(7, f), a.iter().try_fold(7, f_ref)); + assert_eq!(a.iter().cloned().try_rfold(7, f), a.iter().try_rfold(7, f_ref)); + + let a = [10, 20, 30, 40, 100, 60, 70, 80, 90]; + let mut iter = a.iter().cloned(); + assert_eq!(iter.try_fold(0_i8, |acc, x| acc.checked_add(x)), None); + assert_eq!(iter.next(), Some(60)); + let mut iter = a.iter().cloned(); + assert_eq!(iter.try_rfold(0_i8, |acc, x| acc.checked_add(x)), None); + assert_eq!(iter.next_back(), Some(70)); +} + +#[test] +fn test_chain_try_folds() { + let c = || (0..10).chain(10..20); + + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!(c().try_fold(7, f), (0..20).try_fold(7, f)); + assert_eq!(c().try_rfold(7, f), (0..20).rev().try_fold(7, f)); + + let mut iter = c(); + assert_eq!(iter.position(|x| x == 5), Some(5)); + assert_eq!(iter.next(), Some(6), "stopped in front, state Both"); + assert_eq!(iter.position(|x| x == 13), Some(6)); + assert_eq!(iter.next(), Some(14), "stopped in back, state Back"); + assert_eq!(iter.try_fold(0, |acc, x| Some(acc+x)), Some((15..20).sum())); + + let mut iter = c().rev(); // use rev to access try_rfold + assert_eq!(iter.position(|x| x == 15), Some(4)); + assert_eq!(iter.next(), Some(14), "stopped in back, state Both"); + assert_eq!(iter.position(|x| x == 5), Some(8)); + assert_eq!(iter.next(), Some(4), "stopped in front, state Front"); + assert_eq!(iter.try_fold(0, |acc, x| Some(acc+x)), Some((0..4).sum())); + + let mut iter = c(); + iter.by_ref().rev().nth(14); // skip the last 15, ending in state Front + assert_eq!(iter.try_fold(7, f), (0..5).try_fold(7, f)); + + let mut iter = c(); + iter.nth(14); // skip the first 15, ending in state Back + assert_eq!(iter.try_rfold(7, f), (15..20).try_rfold(7, f)); +} + +#[test] +fn test_map_try_folds() { + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((0..10).map(|x| x+3).try_fold(7, f), (3..13).try_fold(7, f)); + assert_eq!((0..10).map(|x| x+3).try_rfold(7, f), (3..13).try_rfold(7, f)); + + let mut iter = (0..40).map(|x| x+10); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(20)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.next_back(), Some(46)); +} + +#[test] +fn test_filter_try_folds() { + fn p(&x: &i32) -> bool { 0 <= x && x < 10 } + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((-10..20).filter(p).try_fold(7, f), (0..10).try_fold(7, f)); + assert_eq!((-10..20).filter(p).try_rfold(7, f), (0..10).try_rfold(7, f)); + + let mut iter = (0..40).filter(|&x| x % 2 == 1); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(25)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.next_back(), Some(31)); +} + +#[test] +fn test_filter_map_try_folds() { + let mp = &|x| if 0 <= x && x < 10 { Some(x*2) } else { None }; + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((-9..20).filter_map(mp).try_fold(7, f), (0..10).map(|x| 2*x).try_fold(7, f)); + assert_eq!((-9..20).filter_map(mp).try_rfold(7, f), (0..10).map(|x| 2*x).try_rfold(7, f)); + + let mut iter = (0..40).filter_map(|x| if x%2 == 1 { None } else { Some(x*2 + 10) }); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(38)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.next_back(), Some(78)); +} + +#[test] +fn test_enumerate_try_folds() { + let f = &|acc, (i, x)| usize::checked_add(2*acc, x/(i+1) + i); + assert_eq!((9..18).enumerate().try_fold(7, f), (0..9).map(|i| (i, i+9)).try_fold(7, f)); + assert_eq!((9..18).enumerate().try_rfold(7, f), (0..9).map(|i| (i, i+9)).try_rfold(7, f)); + + let mut iter = (100..200).enumerate(); + let f = &|acc, (i, x)| u8::checked_add(acc, u8::checked_div(x, i as u8 + 1)?); + assert_eq!(iter.try_fold(0, f), None); + assert_eq!(iter.next(), Some((7, 107))); + assert_eq!(iter.try_rfold(0, f), None); + assert_eq!(iter.next_back(), Some((11, 111))); +} + +#[test] +fn test_peek_try_fold() { + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((1..20).peekable().try_fold(7, f), (1..20).try_fold(7, f)); + let mut iter = (1..20).peekable(); + assert_eq!(iter.peek(), Some(&1)); + assert_eq!(iter.try_fold(7, f), (1..20).try_fold(7, f)); + + let mut iter = [100, 20, 30, 40, 50, 60, 70].iter().cloned().peekable(); + assert_eq!(iter.peek(), Some(&100)); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.peek(), Some(&40)); +} + +#[test] +fn test_skip_while_try_fold() { + let f = &|acc, x| i32::checked_add(2*acc, x); + fn p(&x: &i32) -> bool { (x % 10) <= 5 } + assert_eq!((1..20).skip_while(p).try_fold(7, f), (6..20).try_fold(7, f)); + let mut iter = (1..20).skip_while(p); + assert_eq!(iter.nth(5), Some(11)); + assert_eq!(iter.try_fold(7, f), (12..20).try_fold(7, f)); + + let mut iter = (0..50).skip_while(|&x| (x % 20) < 15); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(23)); +} + +#[test] +fn test_take_while_folds() { + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((1..20).take_while(|&x| x != 10).try_fold(7, f), (1..10).try_fold(7, f)); + let mut iter = (1..20).take_while(|&x| x != 10); + assert_eq!(iter.try_fold(0, |x, y| Some(x+y)), Some((1..10).sum())); + assert_eq!(iter.next(), None, "flag should be set"); + let iter = (1..20).take_while(|&x| x != 10); + assert_eq!(iter.fold(0, |x, y| x+y), (1..10).sum()); + + let mut iter = (10..50).take_while(|&x| x != 40); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(20)); +} + +#[test] +fn test_skip_try_folds() { + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((1..20).skip(9).try_fold(7, f), (10..20).try_fold(7, f)); + assert_eq!((1..20).skip(9).try_rfold(7, f), (10..20).try_rfold(7, f)); + + let mut iter = (0..30).skip(10); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(20)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.next_back(), Some(24)); +} + +#[test] +fn test_take_try_folds() { + let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((10..30).take(10).try_fold(7, f), (10..20).try_fold(7, f)); + //assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).try_rfold(7, f)); + + let mut iter = (10..30).take(20); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(20)); + //assert_eq!(iter.try_rfold(0, i8::checked_add), None); + //assert_eq!(iter.next_back(), Some(24)); +} + +#[test] +fn test_flat_map_try_folds() { + let f = &|acc, x| i32::checked_add(acc*2/3, x); + let mr = &|x| (5*x)..(5*x + 5); + assert_eq!((0..10).flat_map(mr).try_fold(7, f), (0..50).try_fold(7, f)); + assert_eq!((0..10).flat_map(mr).try_rfold(7, f), (0..50).try_rfold(7, f)); + let mut iter = (0..10).flat_map(mr); + iter.next(); iter.next_back(); // have front and back iters in progress + assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f)); + + let mut iter = (0..10).flat_map(|x| (4*x)..(4*x + 4)); + assert_eq!(iter.try_fold(0, i8::checked_add), None); + assert_eq!(iter.next(), Some(17)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.next_back(), Some(35)); +} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 47995597a0a..0e445cdac35 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -24,9 +24,10 @@ #![feature(i128_type)] #![feature(inclusive_range)] #![feature(inclusive_range_syntax)] +#![feature(iterator_try_fold)] #![feature(iter_rfind)] +#![feature(iter_rfold)] #![feature(nonzero)] -#![feature(rand)] #![feature(raw)] #![feature(refcell_replace_swap)] #![feature(sip_hash_13)] @@ -38,15 +39,11 @@ #![feature(test)] #![feature(trusted_len)] #![feature(try_from)] +#![feature(try_trait)] #![feature(unique)] -#![feature(const_atomic_bool_new)] -#![feature(const_atomic_usize_new)] -#![feature(const_atomic_isize_new)] - extern crate core; extern crate test; -extern crate rand; mod any; mod array; diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 86e59c736ba..f55a1c81463 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -121,3 +121,19 @@ fn test_transmute() { } } +#[test] +#[allow(dead_code)] +fn test_discriminant_send_sync() { + enum Regular { + A, + B(i32) + } + enum NotSendSync { + A(*const i32) + } + + fn is_send_sync<T: Send + Sync>() { } + + is_send_sync::<Discriminant<Regular>>(); + is_send_sync::<Discriminant<NotSendSync>>(); +} diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs index 0bca616ea9a..857aae72c8a 100644 --- a/src/libcore/tests/num/flt2dec/estimator.rs +++ b/src/libcore/tests/num/flt2dec/estimator.rs @@ -8,11 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME https://github.com/kripken/emscripten/issues/4563 -// NB we have to actually not compile this test to avoid -// an undefined symbol error -#![cfg(not(target_os = "emscripten"))] - use core::num::flt2dec::estimator::*; #[test] diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs index 0f4d19e7092..ef0178815f9 100644 --- a/src/libcore/tests/num/flt2dec/mod.rs +++ b/src/libcore/tests/num/flt2dec/mod.rs @@ -9,10 +9,7 @@ // except according to those terms. use std::prelude::v1::*; -use std::{str, mem, i16, f32, f64, fmt}; -use std::__rand as rand; -use rand::{Rand, XorShiftRng}; -use rand::distributions::{IndependentSample, Range}; +use std::{str, i16, f32, f64, fmt}; use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign}; @@ -464,87 +461,6 @@ pub fn more_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8] exp: 0, inclusive: false} => b"99999999999999999", 17); } -fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), - V: FnMut(usize) -> Decoded { - assert!(k <= 1024); - - let mut npassed = 0; // f(x) = Some(g(x)) - let mut nignored = 0; // f(x) = None - - for i in 0..n { - if (i & 0xfffff) == 0 { - println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})", - i, n, nignored, npassed, i - nignored - npassed); - } - - let decoded = v(i); - let mut buf1 = [0; 1024]; - if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) { - let mut buf2 = [0; 1024]; - let (len2, e2) = g(&decoded, &mut buf2[..k]); - if e1 == e2 && &buf1[..len1] == &buf2[..len2] { - npassed += 1; - } else { - println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}", - i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1, - str::from_utf8(&buf2[..len2]).unwrap(), e2); - } - } else { - nignored += 1; - } - } - println!("{}({}): done, ignored={} passed={} failed={}", - func, k, nignored, npassed, n - nignored - npassed); - assert!(nignored + npassed == n, - "{}({}): {} out of {} values returns an incorrect value!", - func, k, n - nignored - npassed, n); - (npassed, nignored) -} - -pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); - let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000); - iterate("f32_random_equivalence_test", k, n, f, g, |_| { - let i: u32 = f32_range.ind_sample(&mut rng); - let x: f32 = unsafe {mem::transmute(i)}; - decode_finite(x) - }); -} - -pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); - let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); - iterate("f64_random_equivalence_test", k, n, f, g, |_| { - let i: u64 = f64_range.ind_sample(&mut rng); - let x: f64 = unsafe {mem::transmute(i)}; - decode_finite(x) - }); -} - -pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values, - // so why not simply testing all of them? - // - // this is of course very stressful (and thus should be behind an `#[ignore]` attribute), - // but with `-C opt-level=3 -C lto` this only takes about an hour or so. - - // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges - let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", - k, 0x7f7f_ffff, f, g, |i: usize| { - let x: f32 = unsafe {mem::transmute(i as u32 + 1)}; - decode_finite(x) - }); - assert_eq!((npassed, nignored), (2121451881, 17643158)); -} - fn to_string_with_parts<F>(mut f: F) -> String where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> { let mut buf = [0; 1024]; diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs index 17fb99bcc92..286b39d8cf3 100644 --- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::i16; use super::super::*; use core::num::flt2dec::strategy::grisu::*; @@ -47,35 +46,6 @@ fn shortest_sanity_test() { } #[test] -fn shortest_random_equivalence_test() { - use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); - f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); -} - -#[test] #[ignore] // it is too expensive -fn shortest_f32_exhaustive_equivalence_test() { - // it is hard to directly test the optimality of the output, but we can at least test if - // two different algorithms agree to each other. - // - // this reports the progress and the number of f32 values returned `None`. - // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print: - // `done, ignored=17643158 passed=2121451881 failed=0`. - - use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS); -} - -#[test] #[ignore] // it is too expensive -fn shortest_f64_hard_random_equivalence_test() { - // this again probably has to use appropriate rustc flags. - - use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, - MAX_SIG_DIGITS, 100_000_000); -} - -#[test] fn exact_sanity_test() { // See comments in dragon.rs's exact_sanity_test for why this test is // ignored on MSVC @@ -86,24 +56,6 @@ fn exact_sanity_test() { } #[test] -fn exact_f32_random_equivalence_test() { - use core::num::flt2dec::strategy::dragon::format_exact as fallback; - for k in 1..21 { - f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); - } -} - -#[test] -fn exact_f64_random_equivalence_test() { - use core::num::flt2dec::strategy::dragon::format_exact as fallback; - for k in 1..21 { - f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); - } -} - -#[test] fn test_to_shortest_str() { to_shortest_str_test(format_shortest); } 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/ptr.rs b/src/libcore/tests/ptr.rs index c2d53840f8f..98436f0e1d1 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -62,6 +62,39 @@ fn test_is_null() { let mq = unsafe { mp.offset(1) }; assert!(!mq.is_null()); + + // Pointers to unsized types -- slices + let s: &mut [u8] = &mut [1, 2, 3]; + let cs: *const [u8] = s; + assert!(!cs.is_null()); + + let ms: *mut [u8] = s; + assert!(!ms.is_null()); + + let cz: *const [u8] = &[]; + assert!(!cz.is_null()); + + let mz: *mut [u8] = &mut []; + assert!(!mz.is_null()); + + let ncs: *const [u8] = null::<[u8; 3]>(); + assert!(ncs.is_null()); + + let nms: *mut [u8] = null_mut::<[u8; 3]>(); + assert!(nms.is_null()); + + // Pointers to unsized types -- trait objects + let ci: *const ToString = &3; + assert!(!ci.is_null()); + + let mi: *mut ToString = &mut 3; + assert!(!mi.is_null()); + + let nci: *const ToString = null::<isize>(); + assert!(nci.is_null()); + + let nmi: *mut ToString = null_mut::<isize>(); + assert!(nmi.is_null()); } #[test] @@ -85,6 +118,39 @@ fn test_as_ref() { let p = &u as *const isize; assert_eq!(p.as_ref().unwrap(), &2); } + + // Pointers to unsized types -- slices + let s: &mut [u8] = &mut [1, 2, 3]; + let cs: *const [u8] = s; + assert_eq!(cs.as_ref(), Some(&*s)); + + let ms: *mut [u8] = s; + assert_eq!(ms.as_ref(), Some(&*s)); + + let cz: *const [u8] = &[]; + assert_eq!(cz.as_ref(), Some(&[][..])); + + let mz: *mut [u8] = &mut []; + assert_eq!(mz.as_ref(), Some(&[][..])); + + let ncs: *const [u8] = null::<[u8; 3]>(); + assert_eq!(ncs.as_ref(), None); + + let nms: *mut [u8] = null_mut::<[u8; 3]>(); + assert_eq!(nms.as_ref(), None); + + // Pointers to unsized types -- trait objects + let ci: *const ToString = &3; + assert!(ci.as_ref().is_some()); + + let mi: *mut ToString = &mut 3; + assert!(mi.as_ref().is_some()); + + let nci: *const ToString = null::<isize>(); + assert!(nci.as_ref().is_none()); + + let nmi: *mut ToString = null_mut::<isize>(); + assert!(nmi.as_ref().is_none()); } } @@ -103,6 +169,24 @@ fn test_as_mut() { let p = &mut u as *mut isize; assert!(p.as_mut().unwrap() == &mut 2); } + + // Pointers to unsized types -- slices + let s: &mut [u8] = &mut [1, 2, 3]; + let ms: *mut [u8] = s; + assert_eq!(ms.as_mut(), Some(s)); + + let mz: *mut [u8] = &mut []; + assert_eq!(mz.as_mut(), Some(&mut [][..])); + + let nms: *mut [u8] = null_mut::<[u8; 3]>(); + assert_eq!(nms.as_mut(), None); + + // Pointers to unsized types -- trait objects + let mi: *mut ToString = &mut 3; + assert!(mi.as_mut().is_some()); + + let nmi: *mut ToString = null_mut::<isize>(); + assert!(nmi.as_mut().is_none()); } } 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)); +} diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 8c31d2e83d3..fa4c2e9b373 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -8,29 +8,63 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Ordering::{Equal, Greater, Less}; -use core::slice::heapsort; use core::result::Result::{Ok, Err}; -use rand::{Rng, XorShiftRng}; #[test] fn test_binary_search() { + let b: [i32; 0] = []; + assert_eq!(b.binary_search(&5), Err(0)); + + let b = [4]; + assert_eq!(b.binary_search(&3), Err(0)); + assert_eq!(b.binary_search(&4), Ok(0)); + assert_eq!(b.binary_search(&5), Err(1)); + let b = [1, 2, 4, 6, 8, 9]; - assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3)); - assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3)); - let b = [1, 2, 4, 6, 7, 8, 9]; - assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3)); - assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3)); - let b = [1, 2, 4, 6, 8, 9]; - assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4)); - assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4)); + assert_eq!(b.binary_search(&5), Err(3)); + assert_eq!(b.binary_search(&6), Ok(3)); + assert_eq!(b.binary_search(&7), Err(4)); + assert_eq!(b.binary_search(&8), Ok(4)); + + let b = [1, 2, 4, 5, 6, 8]; + assert_eq!(b.binary_search(&9), Err(6)); + let b = [1, 2, 4, 6, 7, 8, 9]; - assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5)); + assert_eq!(b.binary_search(&6), Ok(3)); + assert_eq!(b.binary_search(&5), Err(3)); + assert_eq!(b.binary_search(&8), Ok(5)); + let b = [1, 2, 4, 5, 6, 8, 9]; - assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5)); - assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0)); - let b = [1, 2, 4, 5, 6, 8]; - assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6)); + assert_eq!(b.binary_search(&7), Err(5)); + assert_eq!(b.binary_search(&0), Err(0)); + + let b = [1, 3, 3, 3, 7]; + assert_eq!(b.binary_search(&0), Err(0)); + assert_eq!(b.binary_search(&1), Ok(0)); + assert_eq!(b.binary_search(&2), Err(1)); + assert!(match b.binary_search(&3) { Ok(1...3) => true, _ => false }); + assert!(match b.binary_search(&3) { Ok(1...3) => true, _ => false }); + assert_eq!(b.binary_search(&4), Err(4)); + assert_eq!(b.binary_search(&5), Err(4)); + assert_eq!(b.binary_search(&6), Err(4)); + assert_eq!(b.binary_search(&7), Ok(4)); + assert_eq!(b.binary_search(&8), Err(5)); +} + +#[test] +// Test implementation specific behavior when finding equivalent elements. +// It is ok to break this test but when you do a crater run is highly advisable. +fn test_binary_search_implementation_details() { + let b = [1, 1, 2, 2, 3, 3, 3]; + assert_eq!(b.binary_search(&1), Ok(1)); + assert_eq!(b.binary_search(&2), Ok(3)); + assert_eq!(b.binary_search(&3), Ok(6)); + let b = [1, 1, 1, 1, 1, 3, 3, 3, 3]; + assert_eq!(b.binary_search(&1), Ok(4)); + assert_eq!(b.binary_search(&3), Ok(8)); + let b = [1, 1, 1, 1, 3, 3, 3, 3, 3]; + assert_eq!(b.binary_search(&1), Ok(3)); + assert_eq!(b.binary_search(&3), Ok(8)); } #[test] @@ -239,6 +273,23 @@ fn test_find_rfind() { } #[test] +fn test_iter_folds() { + let a = [1, 2, 3, 4, 5]; // len>4 so the unroll is used + assert_eq!(a.iter().fold(0, |acc, &x| 2*acc + x), 57); + assert_eq!(a.iter().rfold(0, |acc, &x| 2*acc + x), 129); + let fold = |acc: i32, &x| acc.checked_mul(2)?.checked_add(x); + assert_eq!(a.iter().try_fold(0, &fold), Some(57)); + assert_eq!(a.iter().try_rfold(0, &fold), Some(129)); + + // short-circuiting try_fold, through other methods + let a = [0, 1, 2, 3, 5, 5, 5, 7, 8, 9]; + let mut iter = a.iter(); + assert_eq!(iter.position(|&x| x == 3), Some(3)); + assert_eq!(iter.rfind(|&&x| x == 5), Some(&5)); + assert_eq!(iter.len(), 2); +} + +#[test] fn test_rotate() { const N: usize = 600; let a: &mut [_] = &mut [0; N]; @@ -253,68 +304,3 @@ fn test_rotate() { assert_eq!(a[(i+k)%N], i); } } - -#[test] -fn sort_unstable() { - let mut v = [0; 600]; - let mut tmp = [0; 600]; - let mut rng = XorShiftRng::new_unseeded(); - - for len in (2..25).chain(500..510) { - let v = &mut v[0..len]; - let tmp = &mut tmp[0..len]; - - for &modulus in &[5, 10, 100, 1000] { - for _ in 0..100 { - for i in 0..len { - v[i] = rng.gen::<i32>() % modulus; - } - - // Sort in default order. - tmp.copy_from_slice(v); - tmp.sort_unstable(); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in ascending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| a.cmp(b)); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in descending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| b.cmp(a)); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - - // Test heapsort using `<` operator. - tmp.copy_from_slice(v); - heapsort(tmp, |a, b| a < b); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Test heapsort using `>` operator. - tmp.copy_from_slice(v); - heapsort(tmp, |a, b| a > b); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - } - } - } - - // Sort using a completely random comparison function. - // This will reorder the elements *somehow*, but won't panic. - for i in 0..v.len() { - v[i] = i as i32; - } - v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); - v.sort_unstable(); - for i in 0..v.len() { - assert_eq!(v[i], i as i32); - } - - // Should not panic. - [0i32; 0].sort_unstable(); - [(); 10].sort_unstable(); - [(); 100].sort_unstable(); - - let mut v = [0xDEADBEEFu64]; - v.sort_unstable(); - assert!(v == [0xDEADBEEF]); -} diff --git a/src/libcore/unit.rs b/src/libcore/unit.rs new file mode 100644 index 00000000000..087ddf9688a --- /dev/null +++ b/src/libcore/unit.rs @@ -0,0 +1,31 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use iter::FromIterator; + +/// Collapses all unit items from an iterator into one. +/// +/// This is more useful when combined with higher-level abstractions, like +/// collecting to a `Result<(), E>` where you only care about errors: +/// +/// ``` +/// use std::io::*; +/// let data = vec![1, 2, 3, 4, 5]; +/// let res: Result<()> = data.iter() +/// .map(|x| writeln!(stdout(), "{}", x)) +/// .collect(); +/// assert!(res.is_ok()); +/// ``` +#[stable(feature = "unit_from_iter", since = "1.23.0")] +impl FromIterator<()> for () { + fn from_iter<I: IntoIterator<Item=()>>(iter: I) -> Self { + iter.into_iter().for_each(|()| {}) + } +} |
