From 3016626c3aa4bc44807e54a8ba8b9e367ff566f5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 28 Jun 2016 08:56:56 -0700 Subject: [PATCH] std: Stabilize APIs for the 1.11.0 release Although the set of APIs being stabilized this release is relatively small, the trains keep going! Listed below are the APIs in the standard library which have either transitioned from unstable to stable or those from unstable to deprecated. Stable * `BTreeMap::{append, split_off}` * `BTreeSet::{append, split_off}` * `Cell::get_mut` * `RefCell::get_mut` * `BinaryHeap::append` * `{f32, f64}::{to_degrees, to_radians}` - libcore stabilizations mirroring past libstd stabilizations * `Iterator::sum` * `Iterator::product` Deprecated * `{f32, f64}::next_after` * `{f32, f64}::integer_decode` * `{f32, f64}::ldexp` * `{f32, f64}::frexp` * `num::One` * `num::Zero` Added APIs (all unstable) * `iter::Sum` * `iter::Product` * `iter::Step` - a few methods were added to accomodate deprecation of One/Zero Removed APIs * `From> for RangeInclusive` - everything about `RangeInclusive` is unstable Closes #27739 Closes #27752 Closes #32526 Closes #33444 Closes #34152 cc #34529 (new tracking issue) --- src/libcollections/binary_heap.rs | 6 +- src/libcollections/btree/map.rs | 9 +- src/libcollections/btree/set.rs | 9 +- src/libcollections/lib.rs | 1 - src/libcollectionstest/lib.rs | 4 - src/libcore/cell.rs | 4 +- src/libcore/iter/iterator.rs | 50 +++---- src/libcore/iter/mod.rs | 5 +- src/libcore/iter/range.rs | 169 ++++++++++++++++++----- src/libcore/iter/traits.rs | 101 ++++++++++++++ src/libcore/lib.rs | 2 + src/libcore/num/dec2flt/algorithm.rs | 2 +- src/libcore/num/dec2flt/mod.rs | 14 +- src/libcore/num/dec2flt/rawfp.rs | 35 ++++- src/libcore/num/f32.rs | 8 +- src/libcore/num/f64.rs | 8 +- src/libcore/num/flt2dec/decoder.rs | 9 +- src/libcore/num/mod.rs | 48 +++++-- src/libcore/ops.rs | 24 +--- src/libcoretest/lib.rs | 2 - src/libcoretest/num/dec2flt/rawfp.rs | 23 ++- src/libcoretest/num/flt2dec/estimator.rs | 3 +- src/libcoretest/num/flt2dec/mod.rs | 39 ++++-- src/librustc/lib.rs | 1 - src/librustc_const_eval/lib.rs | 1 - src/librustc_trans/lib.rs | 1 - src/librustc_typeck/lib.rs | 1 - src/libstd/num/f32.rs | 19 +++ src/libstd/num/f64.rs | 17 +++ src/libstd/num/mod.rs | 7 +- src/libstd/sys/unix/mod.rs | 25 +++- src/libstd/sys/windows/mod.rs | 19 ++- src/libstd/sys/windows/net.rs | 24 +++- src/test/compile-fail/range-1.rs | 5 +- src/test/run-pass/range_inclusive.rs | 5 - src/tools/rustbook/main.rs | 1 - 36 files changed, 507 insertions(+), 194 deletions(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 140801737bc4c..b9f5c6fcab909 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -825,8 +825,6 @@ impl BinaryHeap { /// Basic usage: /// /// ``` - /// #![feature(binary_heap_append)] - /// /// use std::collections::BinaryHeap; /// /// let v = vec![-10, 1, 2, 3, 3]; @@ -840,9 +838,7 @@ impl BinaryHeap { /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); /// assert!(b.is_empty()); /// ``` - #[unstable(feature = "binary_heap_append", - reason = "needs to be audited", - issue = "32526")] + #[stable(feature = "binary_heap_append", since = "1.11.0")] pub fn append(&mut self, other: &mut Self) { if self.len() < other.len() { swap(self, other); diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 3b775dc2865ee..aea7a1c13a281 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -559,7 +559,6 @@ impl BTreeMap { /// # Examples /// /// ``` - /// #![feature(btree_append)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); @@ -583,8 +582,7 @@ impl BTreeMap { /// assert_eq!(a[&4], "e"); /// assert_eq!(a[&5], "f"); /// ``` - #[unstable(feature = "btree_append", reason = "recently added as part of collections reform 2", - issue = "34152")] + #[stable(feature = "btree_append", since = "1.11.0")] pub fn append(&mut self, other: &mut Self) { // Do we have to append anything at all? if other.len() == 0 { @@ -914,7 +912,6 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// #![feature(btree_split_off)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); @@ -936,9 +933,7 @@ impl BTreeMap { /// assert_eq!(b[&17], "d"); /// assert_eq!(b[&41], "e"); /// ``` - #[unstable(feature = "btree_split_off", - reason = "recently added as part of collections reform 2", - issue = "34152")] + #[stable(feature = "btree_split_off", since = "1.11.0")] pub fn split_off(&mut self, key: &Q) -> Self where K: Borrow { diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index c47eb0b3fad45..0f885bc2950a6 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -551,7 +551,6 @@ impl BTreeSet { /// # Examples /// /// ``` - /// #![feature(btree_append)] /// use std::collections::BTreeSet; /// /// let mut a = BTreeSet::new(); @@ -575,8 +574,7 @@ impl BTreeSet { /// assert!(a.contains(&4)); /// assert!(a.contains(&5)); /// ``` - #[unstable(feature = "btree_append", reason = "recently added as part of collections reform 2", - issue = "34152")] + #[stable(feature = "btree_append", since = "1.11.0")] pub fn append(&mut self, other: &mut Self) { self.map.append(&mut other.map); } @@ -589,7 +587,6 @@ impl BTreeSet { /// Basic usage: /// /// ``` - /// #![feature(btree_split_off)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); @@ -611,9 +608,7 @@ impl BTreeSet { /// assert_eq!(b[&17], "d"); /// assert_eq!(b[&41], "e"); /// ``` - #[unstable(feature = "btree_split_off", - reason = "recently added as part of collections reform 2", - issue = "34152")] + #[stable(feature = "btree_split_off", since = "1.11.0")] pub fn split_off(&mut self, key: &Q) -> Self where T: Borrow { BTreeSet { map: self.map.split_off(key) } } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 7ac01103d61fe..f027d074cb6f0 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -38,7 +38,6 @@ #![feature(fmt_internals)] #![feature(heap_api)] #![feature(inclusive_range)] -#![feature(iter_arith)] #![feature(lang_items)] #![feature(nonzero)] #![feature(pattern)] diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 6161bad7468c6..8ae63808f2740 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -11,18 +11,14 @@ #![deny(warnings)] #![feature(binary_heap_extras)] -#![feature(binary_heap_append)] #![feature(binary_heap_peek_mut)] #![feature(box_syntax)] -#![feature(btree_append)] -#![feature(btree_split_off)] #![feature(btree_range)] #![feature(collections)] #![feature(collections_bound)] #![feature(const_fn)] #![feature(fn_traits)] #![feature(enumset)] -#![feature(iter_arith)] #![feature(linked_list_contains)] #![feature(pattern)] #![feature(rand)] diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 2700f016751dc..9435be3b0124b 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -238,7 +238,7 @@ impl Cell { /// This call borrows `Cell` mutably (at compile-time) which guarantees /// that we possess the only reference. #[inline] - #[unstable(feature = "cell_get_mut", issue = "33444")] + #[stable(feature = "cell_get_mut", since = "1.11.0")] pub fn get_mut(&mut self) -> &mut T { unsafe { &mut *self.value.get() @@ -509,7 +509,7 @@ impl RefCell { /// This call borrows `RefCell` mutably (at compile-time) so there is no /// need for dynamic checks. #[inline] - #[unstable(feature = "cell_get_mut", issue="33444")] + #[stable(feature = "cell_get_mut", since = "1.11.0")] pub fn get_mut(&mut self) -> &mut T { unsafe { &mut *self.value.get() diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 6f5bb2747df8f..6b01ccaceea2f 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -11,18 +11,16 @@ use clone::Clone; use cmp::{Ord, PartialOrd, PartialEq, Ordering}; use default::Default; -use num::{Zero, One}; -use ops::{Add, FnMut, Mul}; +use ops::FnMut; use option::Option::{self, Some, None}; use marker::Sized; -use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse, - Inspect, Map, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile, Rev, - Zip}; +use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse}; +use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile, Rev}; +use super::{Zip, Sum, Product}; use super::ChainState; -use super::{DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, - IntoIterator}; -use super::ZipImpl; +use super::{DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator}; +use super::{IntoIterator, ZipImpl}; fn _assert_is_object_safe(_: &Iterator) {} @@ -1820,36 +1818,41 @@ pub trait Iterator { /// /// An empty iterator returns the zero value of the type. /// + /// # Panics + /// + /// When calling `sum` and a primitive integer type is being returned, this + /// method will panic if the computation overflows. + /// /// # Examples /// /// Basic usage: /// /// ``` - /// #![feature(iter_arith)] - /// /// let a = [1, 2, 3]; /// let sum: i32 = a.iter().sum(); /// /// assert_eq!(sum, 6); /// ``` - #[unstable(feature = "iter_arith", reason = "bounds recently changed", - issue = "27739")] - fn sum(self) -> S where - S: Add + Zero, - Self: Sized, + #[stable(feature = "iter_arith", since = "1.11.0")] + fn sum(self) -> S + where Self: Sized, + S: Sum, { - self.fold(Zero::zero(), |s, e| s + e) + Sum::sum(self) } /// Iterates over the entire iterator, multiplying all the elements /// /// An empty iterator returns the one value of the type. /// + /// # Panics + /// + /// When calling `product` and a primitive integer type is being returned, + /// this method will panic if the computation overflows. + /// /// # Examples /// /// ``` - /// #![feature(iter_arith)] - /// /// fn factorial(n: u32) -> u32 { /// (1..).take_while(|&i| i <= n).product() /// } @@ -1857,13 +1860,12 @@ pub trait Iterator { /// assert_eq!(factorial(1), 1); /// assert_eq!(factorial(5), 120); /// ``` - #[unstable(feature="iter_arith", reason = "bounds recently changed", - issue = "27739")] - fn product

(self) -> P where - P: Mul + One, - Self: Sized, + #[stable(feature = "iter_arith", since = "1.11.0")] + fn product

(self) -> P + where Self: Sized, + P: Product, { - self.fold(One::one(), |p, e| p * e) + Product::product(self) } /// Lexicographically compares the elements of this `Iterator` with those diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index b866655bbd53d..3ebab266e2ffe 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -327,8 +327,9 @@ pub use self::sources::{Empty, empty}; pub use self::sources::{Once, once}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend, - ExactSizeIterator}; +pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::traits::{ExactSizeIterator, Sum, Product}; mod iterator; mod range; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 08143567beaf3..c234ef21db6d1 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -11,7 +11,6 @@ use clone::Clone; use cmp::PartialOrd; use mem; -use num::{Zero, One}; use ops::{self, Add, Sub}; use option::Option::{self, Some, None}; use marker::Sized; @@ -36,6 +35,24 @@ pub trait Step: PartialOrd + Sized { /// Returns `None` if it is not possible to calculate `steps_between` /// without overflow. fn steps_between(start: &Self, end: &Self, by: &Self) -> Option; + + /// Same as `steps_between`, but with a `by` of 1 + fn steps_between_by_one(start: &Self, end: &Self) -> Option; + + /// Tests whether this step is negative or not (going backwards) + fn is_negative(&self) -> bool; + + /// Replaces this step with `1`, returning itself + fn replace_one(&mut self) -> Self; + + /// Replaces this step with `0`, returning itself + fn replace_zero(&mut self) -> Self; + + /// Adds one to this step, returning the result + fn add_one(&self) -> Self; + + /// Subtracts one to this step, returning the result + fn sub_one(&self) -> Self; } macro_rules! step_impl_unsigned { @@ -65,6 +82,36 @@ macro_rules! step_impl_unsigned { Some(0) } } + + #[inline] + fn is_negative(&self) -> bool { + false + } + + #[inline] + fn replace_one(&mut self) -> Self { + mem::replace(self, 0) + } + + #[inline] + fn replace_zero(&mut self) -> Self { + mem::replace(self, 1) + } + + #[inline] + fn add_one(&self) -> Self { + *self + 1 + } + + #[inline] + fn sub_one(&self) -> Self { + *self - 1 + } + + #[inline] + fn steps_between_by_one(start: &Self, end: &Self) -> Option { + Self::steps_between(start, end, &1) + } } )*) } @@ -106,6 +153,36 @@ macro_rules! step_impl_signed { Some(diff / by_u) } } + + #[inline] + fn is_negative(&self) -> bool { + *self < 0 + } + + #[inline] + fn replace_one(&mut self) -> Self { + mem::replace(self, 0) + } + + #[inline] + fn replace_zero(&mut self) -> Self { + mem::replace(self, 1) + } + + #[inline] + fn add_one(&self) -> Self { + *self + 1 + } + + #[inline] + fn sub_one(&self) -> Self { + *self - 1 + } + + #[inline] + fn steps_between_by_one(start: &Self, end: &Self) -> Option { + Self::steps_between(start, end, &1) + } } )*) } @@ -124,6 +201,37 @@ macro_rules! step_impl_no_between { fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option { None } + + #[inline] + #[allow(unused_comparisons)] + fn is_negative(&self) -> bool { + *self < 0 + } + + #[inline] + fn replace_one(&mut self) -> Self { + mem::replace(self, 0) + } + + #[inline] + fn replace_zero(&mut self) -> Self { + mem::replace(self, 1) + } + + #[inline] + fn add_one(&self) -> Self { + *self + 1 + } + + #[inline] + fn sub_one(&self) -> Self { + *self - 1 + } + + #[inline] + fn steps_between_by_one(start: &Self, end: &Self) -> Option { + Self::steps_between(start, end, &1) + } } )*) } @@ -269,12 +377,12 @@ impl Iterator for StepBy> where } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for StepBy> { +impl Iterator for StepBy> { type Item = A; #[inline] fn next(&mut self) -> Option { - let rev = self.step_by < A::zero(); + let rev = self.step_by.is_negative(); if (rev && self.range.start > self.range.end) || (!rev && self.range.start < self.range.end) { @@ -308,7 +416,7 @@ impl Iterator for StepBy> { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl Iterator for StepBy> { +impl Iterator for StepBy> { type Item = A; #[inline] @@ -322,8 +430,7 @@ impl Iterator for StepBy> { Empty { .. } => return None, // empty iterators yield no values NonEmpty { ref mut start, ref mut end } => { - let zero = A::zero(); - let rev = self.step_by < zero; + let rev = self.step_by.is_negative(); // march start towards (maybe past!) end and yield the old value if (rev && start >= end) || @@ -342,7 +449,7 @@ impl Iterator for StepBy> { } } else { // found range in inconsistent state (start at or past end), so become empty - (Some(mem::replace(end, zero)), None) + (Some(end.replace_zero()), None) } } }; @@ -386,7 +493,7 @@ macro_rules! range_exact_iter_impl { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range where +impl Iterator for ops::Range where for<'a> &'a A: Add<&'a A, Output = A> { type Item = A; @@ -394,7 +501,7 @@ impl Iterator for ops::Range where #[inline] fn next(&mut self) -> Option { if self.start < self.end { - let mut n = &self.start + &A::one(); + let mut n = self.start.add_one(); mem::swap(&mut n, &mut self.start); Some(n) } else { @@ -404,7 +511,7 @@ impl Iterator for ops::Range where #[inline] fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.start, &self.end, &A::one()) { + match Step::steps_between_by_one(&self.start, &self.end) { Some(hint) => (hint, Some(hint)), None => (0, None) } @@ -416,14 +523,14 @@ impl Iterator for ops::Range where range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range where +impl DoubleEndedIterator for ops::Range where for<'a> &'a A: Add<&'a A, Output = A>, for<'a> &'a A: Sub<&'a A, Output = A> { #[inline] fn next_back(&mut self) -> Option { if self.start < self.end { - self.end = &self.end - &A::one(); + self.end = self.end.sub_one(); Some(self.end.clone()) } else { None @@ -432,21 +539,21 @@ impl DoubleEndedIterator for ops::Range where } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::RangeFrom where +impl Iterator for ops::RangeFrom where for<'a> &'a A: Add<&'a A, Output = A> { type Item = A; #[inline] fn next(&mut self) -> Option { - let mut n = &self.start + &A::one(); + let mut n = self.start.add_one(); mem::swap(&mut n, &mut self.start); Some(n) } } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl Iterator for ops::RangeInclusive where +impl Iterator for ops::RangeInclusive where for<'a> &'a A: Add<&'a A, Output = A> { type Item = A; @@ -463,23 +570,22 @@ impl Iterator for ops::RangeInclusive where NonEmpty { ref mut start, ref mut end } => { if start == end { - (Some(mem::replace(end, A::one())), Some(mem::replace(start, A::one()))) + (Some(end.replace_one()), Some(start.replace_one())) } else if start < end { - let one = A::one(); - let mut n = &*start + &one; + let mut n = start.add_one(); mem::swap(&mut n, start); - // if the iterator is done iterating, it will change from NonEmpty to Empty - // to avoid unnecessary drops or clones, we'll reuse either start or end - // (they are equal now, so it doesn't matter which) - // to pull out end, we need to swap something back in -- use the previously - // created A::one() as a dummy value + // if the iterator is done iterating, it will change from + // NonEmpty to Empty to avoid unnecessary drops or clones, + // we'll reuse either start or end (they are equal now, so + // it doesn't matter which) to pull out end, we need to swap + // something back in - (if n == *end { Some(mem::replace(end, one)) } else { None }, + (if n == *end { Some(end.replace_one()) } else { None }, // ^ are we done yet? Some(n)) // < the value to output } else { - (Some(mem::replace(start, A::one())), None) + (Some(start.replace_one()), None) } } }; @@ -500,7 +606,7 @@ impl Iterator for ops::RangeInclusive where Empty { .. } => (0, Some(0)), NonEmpty { ref start, ref end } => - match Step::steps_between(start, end, &A::one()) { + match Step::steps_between_by_one(start, end) { Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), None => (0, None), } @@ -509,7 +615,7 @@ impl Iterator for ops::RangeInclusive where } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl DoubleEndedIterator for ops::RangeInclusive where +impl DoubleEndedIterator for ops::RangeInclusive where for<'a> &'a A: Add<&'a A, Output = A>, for<'a> &'a A: Sub<&'a A, Output = A> { @@ -524,16 +630,15 @@ impl DoubleEndedIterator for ops::RangeInclusive where NonEmpty { ref mut start, ref mut end } => { if start == end { - (Some(mem::replace(start, A::one())), Some(mem::replace(end, A::one()))) + (Some(start.replace_one()), Some(end.replace_one())) } else if start < end { - let one = A::one(); - let mut n = &*end - &one; + let mut n = end.sub_one(); mem::swap(&mut n, end); - (if n == *start { Some(mem::replace(start, one)) } else { None }, + (if n == *start { Some(start.replace_one()) } else { None }, Some(n)) } else { - (Some(mem::replace(end, A::one())), None) + (Some(end.replace_one()), None) } } }; diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 67503984450a4..3549bd6a3bc68 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -524,3 +524,104 @@ pub trait ExactSizeIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I {} +/// Trait to represent types that can be created by summing up an iterator. +/// +/// This trait is used to implement the `sum` method on iterators. Types which +/// implement the trait can be generated by the `sum` method. Like +/// `FromIterator` this trait should rarely be called directly and instead +/// interacted with through `Iterator::sum`. +#[unstable(feature = "iter_arith_traits", issue = "34529")] +pub trait Sum: Sized { + /// Method which takes an iterator and generates `Self` from the elements by + /// "summing up" the items. + fn sum>(iter: I) -> Self; +} + +/// Trait to represent types that can be created by multiplying elements of an +/// iterator. +/// +/// This trait is used to implement the `product` method on iterators. Types +/// which implement the trait can be generated by the `product` method. Like +/// `FromIterator` this trait should rarely be called directly and instead +/// interacted with through `Iterator::product`. +#[unstable(feature = "iter_arith_traits", issue = "34529")] +pub trait Product: Sized { + /// Method which takes an iterator and generates `Self` from the elements by + /// multiplying the items. + fn product>(iter: I) -> Self; +} + +macro_rules! integer_sum_product { + ($($a:ident)*) => ($( + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl Sum for $a { + fn sum>(iter: I) -> $a { + iter.fold(0, |a, b| { + a.checked_add(b).expect("overflow in sum") + }) + } + } + + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl Product for $a { + fn product>(iter: I) -> $a { + iter.fold(1, |a, b| { + a.checked_mul(b).expect("overflow in product") + }) + } + } + + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> $a { + iter.fold(0, |a, b| { + a.checked_add(*b).expect("overflow in sum") + }) + } + } + + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl<'a> Product<&'a $a> for $a { + fn product>(iter: I) -> $a { + iter.fold(1, |a, b| { + a.checked_mul(*b).expect("overflow in product") + }) + } + } + )*) +} + +macro_rules! float_sum_product { + ($($a:ident)*) => ($( + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl Sum for $a { + fn sum>(iter: I) -> $a { + iter.fold(0.0, |a, b| a + b) + } + } + + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl Product for $a { + fn product>(iter: I) -> $a { + iter.fold(1.0, |a, b| a * b) + } + } + + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> $a { + iter.fold(0.0, |a, b| a + *b) + } + } + + #[unstable(feature = "iter_arith_traits", issue = "34529")] + impl<'a> Product<&'a $a> for $a { + fn product>(iter: I) -> $a { + iter.fold(1.0, |a, b| a * *b) + } + } + )*) +} + +integer_sum_product! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } +float_sum_product! { f32 f64 } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index db73f4759a5ff..e849369d647c4 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -59,6 +59,8 @@ #![deny(missing_debug_implementations)] #![cfg_attr(not(stage0), deny(warnings))] +#![cfg_attr(stage0, allow(unused_attributes))] + #![feature(allow_internal_unstable)] #![feature(asm)] #![feature(associated_type_defaults)] diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index c7af46a1e4f6b..4761727cec03f 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -321,7 +321,7 @@ pub fn algorithm_m(f: &Big, e: i16) -> T { return underflow(x, v, rem); } if k > T::max_exp_int() { - return T::infinity(); + return T::infinity2(); } if x < min_sig { u.mul_pow2(1); diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 022bd84f4c841..ff2d85307b106 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -215,11 +215,11 @@ fn dec2flt(s: &str) -> Result { let (sign, s) = extract_sign(s); let flt = match parse_decimal(s) { ParseResult::Valid(decimal) => convert(decimal)?, - ParseResult::ShortcutToInf => T::infinity(), - ParseResult::ShortcutToZero => T::zero(), + ParseResult::ShortcutToInf => T::infinity2(), + ParseResult::ShortcutToZero => T::zero2(), ParseResult::Invalid => match s { - "inf" => T::infinity(), - "NaN" => T::nan(), + "inf" => T::infinity2(), + "NaN" => T::nan2(), _ => { return Err(pfe_invalid()); } } }; @@ -316,7 +316,7 @@ fn bound_intermediate_digits(decimal: &Decimal, e: i64) -> u64 { fn trivial_cases(decimal: &Decimal) -> Option { // There were zeros but they were stripped by simplify() if decimal.integral.is_empty() && decimal.fractional.is_empty() { - return Some(T::zero()); + return Some(T::zero2()); } // This is a crude approximation of ceil(log10(the real value)). We don't need to worry too // much about overflow here because the input length is tiny (at least compared to 2^64) and @@ -324,9 +324,9 @@ fn trivial_cases(decimal: &Decimal) -> Option { // (which is still 10^19 short of 2^64). let max_place = decimal.exp + decimal.integral.len() as i64; if max_place > T::inf_cutoff() { - return Some(T::infinity()); + return Some(T::infinity2()); } else if max_place < T::zero_cutoff() { - return Some(T::zero()); + return Some(T::zero2()); } None } diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index 2099c6a7baa76..68e4dc4b359ef 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -61,6 +61,27 @@ impl Unpacked { pub trait RawFloat : Float + Copy + Debug + LowerExp + Mul + Div + Neg { + // suffix of "2" because Float::infinity is deprecated + #[allow(deprecated)] + fn infinity2() -> Self { + Float::infinity() + } + + // suffix of "2" because Float::nan is deprecated + #[allow(deprecated)] + fn nan2() -> Self { + Float::nan() + } + + // suffix of "2" because Float::zero is deprecated + fn zero2() -> Self; + + // suffix of "2" because Float::integer_decode is deprecated + #[allow(deprecated)] + fn integer_decode2(self) -> (u64, i16, i8) { + Float::integer_decode(self) + } + /// Get the raw binary representation of the float. fn transmute(self) -> u64; @@ -146,6 +167,10 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp } impl RawFloat for f32 { + fn zero2() -> Self { + 0.0 + } + fn sig_bits() -> u8 { 24 } @@ -169,7 +194,7 @@ impl RawFloat for f32 { } fn unpack(self) -> Unpacked { - let (sig, exp, _sig) = self.integer_decode(); + let (sig, exp, _sig) = self.integer_decode2(); Unpacked::new(sig, exp) } @@ -198,6 +223,10 @@ impl RawFloat for f32 { impl RawFloat for f64 { + fn zero2() -> Self { + 0.0 + } + fn sig_bits() -> u8 { 53 } @@ -220,7 +249,7 @@ impl RawFloat for f64 { } fn unpack(self) -> Unpacked { - let (sig, exp, _sig) = self.integer_decode(); + let (sig, exp, _sig) = self.integer_decode2(); Unpacked::new(sig, exp) } @@ -351,7 +380,7 @@ pub fn prev_float(x: T) -> T { pub fn next_float(x: T) -> T { match x.classify() { Nan => panic!("next_float: argument is NaN"), - Infinite => T::infinity(), + Infinite => T::infinity2(), // This seems too good to be true, but it works. // 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa. // In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F. diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index c24eaa3eabc75..79e1462eaa135 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -168,7 +168,7 @@ impl Float for f32 { /// Returns `true` if the number is infinite. #[inline] fn is_infinite(self) -> bool { - self == Float::infinity() || self == Float::neg_infinity() + self == INFINITY || self == NEG_INFINITY } /// Returns `true` if the number is neither infinite or NaN. @@ -230,7 +230,7 @@ impl Float for f32 { #[inline] fn signum(self) -> f32 { if self.is_nan() { - Float::nan() + NAN } else { unsafe { intrinsics::copysignf32(1.0, self) } } @@ -240,14 +240,14 @@ impl Float for f32 { /// `Float::infinity()`. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == Float::infinity() + self > 0.0 || (1.0 / self) == INFINITY } /// Returns `true` if `self` is negative, including `-0.0` and /// `Float::neg_infinity()`. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == Float::neg_infinity() + self < 0.0 || (1.0 / self) == NEG_INFINITY } /// Returns the reciprocal (multiplicative inverse) of the number. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index beeee80902525..35557f61c4542 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -168,7 +168,7 @@ impl Float for f64 { /// Returns `true` if the number is infinite. #[inline] fn is_infinite(self) -> bool { - self == Float::infinity() || self == Float::neg_infinity() + self == INFINITY || self == NEG_INFINITY } /// Returns `true` if the number is neither infinite or NaN. @@ -230,7 +230,7 @@ impl Float for f64 { #[inline] fn signum(self) -> f64 { if self.is_nan() { - Float::nan() + NAN } else { unsafe { intrinsics::copysignf64(1.0, self) } } @@ -240,14 +240,14 @@ impl Float for f64 { /// `Float::infinity()`. #[inline] fn is_sign_positive(self) -> bool { - self > 0.0 || (1.0 / self) == Float::infinity() + self > 0.0 || (1.0 / self) == INFINITY } /// Returns `true` if `self` is negative, including `-0.0` and /// `Float::neg_infinity()`. #[inline] fn is_sign_negative(self) -> bool { - self < 0.0 || (1.0 / self) == Float::neg_infinity() + self < 0.0 || (1.0 / self) == NEG_INFINITY } /// Returns the reciprocal (multiplicative inverse) of the number. diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index 6265691bde9e9..5420e7bdd2a5a 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -13,7 +13,8 @@ use prelude::v1::*; use {f32, f64}; -use num::{Float, FpCategory}; +use num::FpCategory; +use num::dec2flt::rawfp::RawFloat; /// Decoded unsigned finite value, such that: /// @@ -52,7 +53,7 @@ pub enum FullDecoded { } /// A floating point type which can be `decode`d. -pub trait DecodableFloat: Float + Copy { +pub trait DecodableFloat: RawFloat + Copy { /// The minimum positive normalized value. fn min_pos_norm_value() -> Self; } @@ -68,7 +69,7 @@ impl DecodableFloat for f64 { /// Returns a sign (true when negative) and `FullDecoded` value /// from given floating point number. pub fn decode(v: T) -> (/*negative?*/ bool, FullDecoded) { - let (mant, exp, sign) = v.integer_decode(); + let (mant, exp, sign) = v.integer_decode2(); let even = (mant & 1) == 0; let decoded = match v.classify() { FpCategory::Nan => FullDecoded::Nan, @@ -82,7 +83,7 @@ pub fn decode(v: T) -> (/*negative?*/ bool, FullDecoded) { exp: exp, inclusive: even }) } FpCategory::Normal => { - let minnorm = ::min_pos_norm_value().integer_decode(); + let minnorm = ::min_pos_norm_value().integer_decode2(); if mant == minnorm.0 { // neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp) // where maxmant = minnormmant * 2 - 1 diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 06398fc094e85..0d79398a8f1d5 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -109,6 +109,8 @@ pub mod diy_float; #[unstable(feature = "zero_one", reason = "unsure of placement, wants to use associated constants", issue = "27739")] +#[rustc_deprecated(since = "1.11.0", reason = "no longer used for \ + Iterator::sum")] pub trait Zero: Sized { /// The "zero" (usually, additive identity) for this type. fn zero() -> Self; @@ -121,6 +123,8 @@ pub trait Zero: Sized { #[unstable(feature = "zero_one", reason = "unsure of placement, wants to use associated constants", issue = "27739")] +#[rustc_deprecated(since = "1.11.0", reason = "no longer used for \ + Iterator::product")] pub trait One: Sized { /// The "one" (usually, multiplicative identity) for this type. fn one() -> Self; @@ -131,6 +135,7 @@ macro_rules! zero_one_impl { #[unstable(feature = "zero_one", reason = "unsure of placement, wants to use associated constants", issue = "27739")] + #[allow(deprecated)] impl Zero for $t { #[inline] fn zero() -> Self { 0 } @@ -138,6 +143,7 @@ macro_rules! zero_one_impl { #[unstable(feature = "zero_one", reason = "unsure of placement, wants to use associated constants", issue = "27739")] + #[allow(deprecated)] impl One for $t { #[inline] fn one() -> Self { 1 } @@ -151,6 +157,7 @@ macro_rules! zero_one_impl_float { #[unstable(feature = "zero_one", reason = "unsure of placement, wants to use associated constants", issue = "27739")] + #[allow(deprecated)] impl Zero for $t { #[inline] fn zero() -> Self { 0.0 } @@ -158,6 +165,7 @@ macro_rules! zero_one_impl_float { #[unstable(feature = "zero_one", reason = "unsure of placement, wants to use associated constants", issue = "27739")] + #[allow(deprecated)] impl One for $t { #[inline] fn one() -> Self { 1.0 } @@ -604,7 +612,7 @@ macro_rules! int_impl { pub fn saturating_add(self, other: Self) -> Self { match self.checked_add(other) { Some(x) => x, - None if other >= Self::zero() => Self::max_value(), + None if other >= 0 => Self::max_value(), None => Self::min_value(), } } @@ -625,7 +633,7 @@ macro_rules! int_impl { pub fn saturating_sub(self, other: Self) -> Self { match self.checked_sub(other) { Some(x) => x, - None if other >= Self::zero() => Self::min_value(), + None if other >= 0 => Self::min_value(), None => Self::max_value(), } } @@ -1064,7 +1072,7 @@ macro_rules! int_impl { #[rustc_inherit_overflow_checks] pub fn pow(self, mut exp: u32) -> Self { let mut base = self; - let mut acc = Self::one(); + let mut acc = 1; while exp > 1 { if (exp & 1) == 1 { @@ -2092,7 +2100,7 @@ macro_rules! uint_impl { #[rustc_inherit_overflow_checks] pub fn pow(self, mut exp: u32) -> Self { let mut base = self; - let mut acc = Self::one(); + let mut acc = 1; let mut prev_base = self; let mut base_oflo = false; @@ -2129,8 +2137,7 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_power_of_two(self) -> bool { - (self.wrapping_sub(Self::one())) & self == Self::zero() && - !(self == Self::zero()) + (self.wrapping_sub(1)) & self == 0 && !(self == 0) } /// Returns the smallest power of two greater than or equal to `self`. @@ -2148,7 +2155,7 @@ macro_rules! uint_impl { #[inline] pub fn next_power_of_two(self) -> Self { let bits = size_of::() * 8; - let one: Self = Self::one(); + let one: Self = 1; one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) } @@ -2303,26 +2310,44 @@ pub trait Float: Sized { /// Returns the NaN value. #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn nan() -> Self; /// Returns the infinite value. #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn infinity() -> Self; /// Returns the negative infinite value. #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn neg_infinity() -> Self; /// Returns -0.0. #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn neg_zero() -> Self; /// Returns 0.0. #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn zero() -> Self; /// Returns 1.0. #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn one() -> Self; /// Returns true if this value is NaN and false otherwise. @@ -2345,6 +2370,9 @@ pub trait Float: Sized { /// Returns the mantissa, exponent and sign as integers, respectively. #[unstable(feature = "float_extras", reason = "signature is undecided", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] fn integer_decode(self) -> (u64, i16, i8); /// Computes the absolute value of `self`. Returns `Float::nan()` if the @@ -2379,12 +2407,10 @@ pub trait Float: Sized { fn powi(self, n: i32) -> Self; /// Convert radians to degrees. - #[unstable(feature = "float_extras", reason = "desirability is unclear", - issue = "27752")] + #[stable(feature = "deg_rad_conversions", since="1.7.0")] fn to_degrees(self) -> Self; /// Convert degrees to radians. - #[unstable(feature = "float_extras", reason = "desirability is unclear", - issue = "27752")] + #[stable(feature = "deg_rad_conversions", since="1.7.0")] fn to_radians(self) -> Self; } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 7258c8a1b6b3d..7753aae147a88 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -69,9 +69,7 @@ use cmp::PartialOrd; use fmt; -use convert::From; use marker::{Sized, Unsize}; -use num::One; /// The `Drop` trait is used to run some code when a value goes out of scope. /// This is sometimes called a 'destructor'. @@ -1494,7 +1492,6 @@ impl fmt::Debug for RangeFull { /// # Examples /// /// ``` -/// #![feature(iter_arith)] /// fn main() { /// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 }); /// assert_eq!(3+4+5, (3..6).sum()); @@ -1558,7 +1555,6 @@ impl> Range { /// # Examples /// /// ``` -/// #![feature(iter_arith)] /// fn main() { /// assert_eq!((2..), std::ops::RangeFrom{ start: 2 }); /// assert_eq!(2+3+4, (2..).take(3).sum()); @@ -1660,7 +1656,7 @@ impl> RangeTo { /// # Examples /// /// ``` -/// #![feature(inclusive_range,inclusive_range_syntax,iter_arith)] +/// #![feature(inclusive_range,inclusive_range_syntax)] /// fn main() { /// assert_eq!((3...5), std::ops::RangeInclusive::NonEmpty{ start: 3, end: 5 }); /// assert_eq!(3+4+5, (3...5).sum()); @@ -1714,24 +1710,6 @@ impl fmt::Debug for RangeInclusive { } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl> From> for RangeInclusive { - fn from(range: Range) -> RangeInclusive { - use self::RangeInclusive::*; - - if range.start < range.end { - NonEmpty { - start: range.start, - end: range.end - Idx::one() // can't underflow because end > start >= MIN - } - } else { - Empty { - at: range.start - } - } - } -} - #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] impl> RangeInclusive { /// # Examples diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 88d73df937f7e..c6bceab793125 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -19,9 +19,7 @@ #![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(fixed_size_array)] -#![feature(float_extras)] #![feature(flt2dec)] -#![feature(iter_arith)] #![feature(libc)] #![feature(nonzero)] #![feature(rand)] diff --git a/src/libcoretest/num/dec2flt/rawfp.rs b/src/libcoretest/num/dec2flt/rawfp.rs index 4c0a403e574a3..1a3533317dae6 100644 --- a/src/libcoretest/num/dec2flt/rawfp.rs +++ b/src/libcoretest/num/dec2flt/rawfp.rs @@ -9,9 +9,24 @@ // except according to those terms. use std::f64; +use std::mem; use core::num::diy_float::Fp; use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal}; +fn integer_decode(f: f64) -> (u64, i16, i8) { + let bits: u64 = unsafe { mem::transmute(f) }; + let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; + let mantissa = if exponent == 0 { + (bits & 0xfffffffffffff) << 1 + } else { + (bits & 0xfffffffffffff) | 0x10000000000000 + }; + // Exponent bias + mantissa shift + exponent -= 1023 + 52; + (mantissa, exponent, sign) +} + #[test] fn fp_to_float_half_to_even() { fn is_normalized(sig: u64) -> bool { @@ -21,12 +36,12 @@ fn fp_to_float_half_to_even() { fn conv(sig: u64) -> u64 { // The significands are perfectly in range, so the exponent should not matter - let (m1, e1, _) = fp_to_float::(Fp { f: sig, e: 0 }).integer_decode(); + let (m1, e1, _) = integer_decode(fp_to_float::(Fp { f: sig, e: 0 })); assert_eq!(e1, 0 + 64 - 53); - let (m2, e2, _) = fp_to_float::(Fp { f: sig, e: 55 }).integer_decode(); + let (m2, e2, _) = integer_decode(fp_to_float::(Fp { f: sig, e: 55 })); assert_eq!(e2, 55 + 64 - 53); assert_eq!(m2, m1); - let (m3, e3, _) = fp_to_float::(Fp { f: sig, e: -78 }).integer_decode(); + let (m3, e3, _) = integer_decode(fp_to_float::(Fp { f: sig, e: -78 })); assert_eq!(e3, -78 + 64 - 53); assert_eq!(m3, m2); m3 @@ -65,7 +80,7 @@ const SOME_FLOATS: [f64; 9] = #[test] fn human_f64_roundtrip() { for &x in &SOME_FLOATS { - let (f, e, _) = x.integer_decode(); + let (f, e, _) = integer_decode(x); let fp = Fp { f: f, e: e}; assert_eq!(fp_to_float::(fp), x); } diff --git a/src/libcoretest/num/flt2dec/estimator.rs b/src/libcoretest/num/flt2dec/estimator.rs index 21260c520f623..857aae72c8a5b 100644 --- a/src/libcoretest/num/flt2dec/estimator.rs +++ b/src/libcoretest/num/flt2dec/estimator.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::f64; use core::num::flt2dec::estimator::*; #[test] @@ -54,7 +53,7 @@ fn test_estimate_scaling_factor() { assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309); for i in -1074..972 { - let expected = f64::ldexp(1.0, i).log10().ceil(); + let expected = super::ldexp_f64(1.0, i).log10().ceil(); assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16); } } diff --git a/src/libcoretest/num/flt2dec/mod.rs b/src/libcoretest/num/flt2dec/mod.rs index 1a592f3ad4249..0f4d19e709257 100644 --- a/src/libcoretest/num/flt2dec/mod.rs +++ b/src/libcoretest/num/flt2dec/mod.rs @@ -89,6 +89,17 @@ macro_rules! try_fixed { }) } +fn ldexp_f32(a: f32, b: i32) -> f32 { + ldexp_f64(a as f64, b) as f32 +} + +fn ldexp_f64(a: f64, b: i32) -> f64 { + extern { + fn ldexp(x: f64, n: i32) -> f64; + } + unsafe { ldexp(a, b) } +} + fn check_exact(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16) where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { // use a large enough buffer @@ -237,7 +248,7 @@ pub fn f32_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) // 10^8 * 0.3355443 // 10^8 * 0.33554432 // 10^8 * 0.33554436 - check_shortest!(f(f32::ldexp(1.0, 25)) => b"33554432", 8); + check_shortest!(f(ldexp_f32(1.0, 25)) => b"33554432", 8); // 10^39 * 0.340282326356119256160033759537265639424 // 10^39 * 0.34028234663852885981170418348451692544 @@ -252,13 +263,13 @@ pub fn f32_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) // 10^-44 * 0 // 10^-44 * 0.1401298464324817070923729583289916131280... // 10^-44 * 0.2802596928649634141847459166579832262560... - let minf32 = f32::ldexp(1.0, -149); + let minf32 = ldexp_f32(1.0, -149); check_shortest!(f(minf32) => b"1", -44); } pub fn f32_exact_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { - let minf32 = f32::ldexp(1.0, -149); + let minf32 = ldexp_f32(1.0, -149); check_exact!(f(0.1f32) => b"100000001490116119384765625 ", 0); check_exact!(f(0.5f32) => b"5 ", 0); @@ -336,7 +347,7 @@ pub fn f64_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) // 10^20 * 0.18446744073709549568 // 10^20 * 0.18446744073709551616 // 10^20 * 0.18446744073709555712 - check_shortest!(f(f64::ldexp(1.0, 64)) => b"18446744073709552", 20); + check_shortest!(f(ldexp_f64(1.0, 64)) => b"18446744073709552", 20); // pathological case: high = 10^23 (exact). tie breaking should always prefer that. // 10^24 * 0.099999999999999974834176 @@ -357,13 +368,13 @@ pub fn f64_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) // 10^-323 * 0 // 10^-323 * 0.4940656458412465441765687928682213723650... // 10^-323 * 0.9881312916824930883531375857364427447301... - let minf64 = f64::ldexp(1.0, -1074); + let minf64 = ldexp_f64(1.0, -1074); check_shortest!(f(minf64) => b"5", -323); } pub fn f64_exact_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { - let minf64 = f64::ldexp(1.0, -1074); + let minf64 = ldexp_f64(1.0, -1074); check_exact!(f(0.1f64) => b"1000000000000000055511151231257827021181", 0); check_exact!(f(0.45f64) => b"4500000000000000111022302462515654042363", 0); @@ -616,7 +627,7 @@ pub fn to_shortest_str_test(mut f_: F) assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", "")); assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", "")); - let minf32 = f32::ldexp(1.0, -149); + let minf32 = ldexp_f32(1.0, -149); assert_eq!(to_string(f, minf32, Minus, 0, false), format!("0.{:0>44}1", "")); assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", "")); assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", "")); @@ -628,7 +639,7 @@ pub fn to_shortest_str_test(mut f_: F) assert_eq!(to_string(f, f64::MAX, Minus, 8, false), format!("17976931348623157{:0>292}.00000000", "")); - let minf64 = f64::ldexp(1.0, -1074); + let minf64 = ldexp_f64(1.0, -1074); assert_eq!(to_string(f, minf64, Minus, 0, false), format!("0.{:0>323}5", "")); assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", "")); assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", "")); @@ -730,7 +741,7 @@ pub fn to_shortest_exp_str_test(mut f_: F) assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38"); assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", "")); - let minf32 = f32::ldexp(1.0, -149); + let minf32 = ldexp_f32(1.0, -149); assert_eq!(to_string(f, minf32, Minus, ( -4, 16), false), "1e-45"); assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45"); assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", "")); @@ -742,7 +753,7 @@ pub fn to_shortest_exp_str_test(mut f_: F) assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false), "1.7976931348623157e308"); - let minf64 = f64::ldexp(1.0, -1074); + let minf64 = ldexp_f64(1.0, -1074); assert_eq!(to_string(f, minf64, Minus, ( -4, 16), false), "5e-324"); assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", "")); assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324"); @@ -874,7 +885,7 @@ pub fn to_exact_exp_str_test(mut f_: F) assert_eq!(to_string(f, f32::MAX, Minus, 64, false), "3.402823466385288598117041834845169254400000000000000000000000000e38"); - let minf32 = f32::ldexp(1.0, -149); + let minf32 = ldexp_f32(1.0, -149); assert_eq!(to_string(f, minf32, Minus, 1, false), "1e-45"); assert_eq!(to_string(f, minf32, Minus, 2, false), "1.4e-45"); assert_eq!(to_string(f, minf32, Minus, 4, false), "1.401e-45"); @@ -914,7 +925,7 @@ pub fn to_exact_exp_str_test(mut f_: F) 0000000000000000000000000000000000000000000000000000000000000000e308"); // okay, this is becoming tough. fortunately for us, this is almost the worst case. - let minf64 = f64::ldexp(1.0, -1074); + let minf64 = ldexp_f64(1.0, -1074); assert_eq!(to_string(f, minf64, Minus, 1, false), "5e-324"); assert_eq!(to_string(f, minf64, Minus, 2, false), "4.9e-324"); assert_eq!(to_string(f, minf64, Minus, 4, false), "4.941e-324"); @@ -1120,7 +1131,7 @@ pub fn to_exact_fixed_str_test(mut f_: F) assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "340282346638528859811704183484516925440.00"); - let minf32 = f32::ldexp(1.0, -149); + let minf32 = ldexp_f32(1.0, -149); assert_eq!(to_string(f, minf32, Minus, 0, false), "0"); assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0"); assert_eq!(to_string(f, minf32, Minus, 2, false), "0.00"); @@ -1152,7 +1163,7 @@ pub fn to_exact_fixed_str_test(mut f_: F) 9440758685084551339423045832369032229481658085593321233482747978\ 26204144723168738177180919299881250404026184124858368.0000000000"); - let minf64 = f64::ldexp(1.0, -1074); + let minf64 = ldexp_f64(1.0, -1074); assert_eq!(to_string(f, minf64, Minus, 0, false), "0"); assert_eq!(to_string(f, minf64, Minus, 1, false), "0.0"); assert_eq!(to_string(f, minf64, Minus, 10, false), "0.0000000000"); diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index eb9dd7dfcb36f..48ea953cc1e8b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -30,7 +30,6 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(enumset)] -#![feature(iter_arith)] #![feature(libc)] #![feature(nonzero)] #![feature(quote)] diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 2da9a55f1fd44..726ba4fc1924f 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -27,7 +27,6 @@ #![feature(staged_api)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![feature(iter_arith)] #![feature(question_mark)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index c369858556d3a..9cb5d8b6ad62a 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -28,7 +28,6 @@ #![feature(const_fn)] #![feature(custom_attribute)] #![allow(unused_attributes)] -#![feature(iter_arith)] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 7ccff7ad3d87c..6239506c2d780 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -76,7 +76,6 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(iter_arith)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 17d412411c048..7a676c041ad89 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -110,6 +110,7 @@ mod cmath { } #[inline] + #[allow(deprecated)] pub unsafe fn frexpf(x: c_float, value: &mut c_int) -> c_float { let (a, b) = f64::frexp(x as f64); *value = b as c_int; @@ -117,6 +118,7 @@ mod cmath { } #[inline] + #[allow(deprecated)] pub unsafe fn ldexpf(x: c_float, n: c_int) -> c_float { f64::ldexp(x as f64, n as isize) as c_float } @@ -265,7 +267,11 @@ impl f32 { /// [floating-point]: ../reference.html#machine-types #[unstable(feature = "float_extras", reason = "signature is undecided", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] + #[allow(deprecated)] pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } @@ -718,6 +724,9 @@ impl f32 { #[unstable(feature = "float_extras", reason = "pending integer conventions", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] pub fn ldexp(x: f32, exp: isize) -> f32 { unsafe { cmath::ldexpf(x, exp as c_int) } @@ -747,6 +756,9 @@ impl f32 { #[unstable(feature = "float_extras", reason = "pending integer conventions", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] pub fn frexp(self) -> (f32, isize) { unsafe { @@ -773,6 +785,9 @@ impl f32 { #[unstable(feature = "float_extras", reason = "unsure about its place in the world", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] pub fn next_after(self, other: f32) -> f32 { unsafe { cmath::nextafterf(self, other) } @@ -1384,6 +1399,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_integer_decode() { assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1)); assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1)); @@ -1711,6 +1727,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_ldexp() { let f1 = 2.0f32.powi(-123); let f2 = 2.0f32.powi(-111); @@ -1731,6 +1748,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_frexp() { let f1 = 2.0f32.powi(-123); let f2 = 2.0f32.powi(-111); @@ -1750,6 +1768,7 @@ mod tests { } #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 + #[allow(deprecated)] fn test_frexp_nowin() { let inf: f32 = f32::INFINITY; let neg_inf: f32 = f32::NEG_INFINITY; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 70b7706535ca1..67a1c302483d2 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -209,7 +209,11 @@ impl f64 { /// [floating-point]: ../reference.html#machine-types #[unstable(feature = "float_extras", reason = "signature is undecided", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] + #[allow(deprecated)] pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } /// Returns the largest integer less than or equal to a number. @@ -613,6 +617,9 @@ impl f64 { #[unstable(feature = "float_extras", reason = "pending integer conventions", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] pub fn ldexp(x: f64, exp: isize) -> f64 { unsafe { cmath::ldexp(x, exp as c_int) } @@ -640,6 +647,9 @@ impl f64 { #[unstable(feature = "float_extras", reason = "pending integer conventions", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] pub fn frexp(self) -> (f64, isize) { unsafe { @@ -664,6 +674,9 @@ impl f64 { #[unstable(feature = "float_extras", reason = "unsure about its place in the world", issue = "27752")] + #[rustc_deprecated(since = "1.11.0", + reason = "never really came to fruition and easily \ + implementable outside the standard library")] #[inline] pub fn next_after(self, other: f64) -> f64 { unsafe { cmath::nextafter(self, other) } @@ -1277,6 +1290,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_integer_decode() { assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1)); assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1)); @@ -1604,6 +1618,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_ldexp() { let f1 = 2.0f64.powi(-123); let f2 = 2.0f64.powi(-111); @@ -1624,6 +1639,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_frexp() { let f1 = 2.0f64.powi(-123); let f2 = 2.0f64.powi(-111); @@ -1643,6 +1659,7 @@ mod tests { } #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 + #[allow(deprecated)] fn test_frexp_nowin() { let inf: f64 = INFINITY; let neg_inf: f64 = NEG_INFINITY; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index d33df05acf224..20804d62dfab6 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -17,6 +17,7 @@ #![allow(missing_docs)] #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub use core::num::{Zero, One}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError}; @@ -46,7 +47,6 @@ pub fn test_num(ten: T, two: T) where #[cfg(test)] mod tests { - use super::*; use u8; use u16; use u32; @@ -198,15 +198,14 @@ mod tests { #[test] fn test_pow() { - fn naive_pow + One + Copy>(base: T, exp: usize) -> T { - let one: T = T::one(); + fn naive_pow + Copy>(one: T, base: T, exp: usize) -> T { (0..exp).fold(one, |acc, _| acc * base) } macro_rules! assert_pow { (($num:expr, $exp:expr) => $expected:expr) => {{ let result = $num.pow($exp); assert_eq!(result, $expected); - assert_eq!(result, naive_pow($num, $exp)); + assert_eq!(result, naive_pow(1, $num, $exp)); }} } assert_pow!((3u32, 0 ) => 1); diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 12a877f747820..f0fd42fc99b80 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -12,8 +12,6 @@ use io::{self, ErrorKind}; use libc; -use num::One; -use ops::Neg; #[cfg(target_os = "android")] pub use os::android as platform; #[cfg(target_os = "bitrig")] pub use os::bitrig as platform; @@ -123,9 +121,23 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } } -pub fn cvt>(t: T) -> io::Result { - let one: T = T::one(); - if t == -one { +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +pub fn cvt(t: T) -> io::Result { + if t.is_minus_one() { Err(io::Error::last_os_error()) } else { Ok(t) @@ -133,7 +145,8 @@ pub fn cvt>(t: T) -> io::Result { } pub fn cvt_r(mut f: F) -> io::Result - where T: One + PartialEq + Neg, F: FnMut() -> T + where T: IsMinusOne, + F: FnMut() -> T { loop { match cvt(f()) { diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 6dd4f4c3e750e..12219c1e9d42b 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -14,7 +14,6 @@ use prelude::v1::*; use ffi::{OsStr, OsString}; use io::{self, ErrorKind}; -use num::Zero; use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; use time::Duration; @@ -178,8 +177,22 @@ pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { } } -fn cvt(i: I) -> io::Result { - if i == I::zero() { +trait IsZero { + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { + ($($t:ident)*) => ($(impl IsZero for $t { + fn is_zero(&self) -> bool { + *self == 0 + } + })*) +} + +impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } + +fn cvt(i: I) -> io::Result { + if i.is_zero() { Err(io::Error::last_os_error()) } else { Ok(i) diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index b05dcf42a3324..71e164f012f1f 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -17,8 +17,6 @@ use io::{self, Read}; use libc::{c_int, c_void, c_ulong}; use mem; use net::{SocketAddr, Shutdown}; -use num::One; -use ops::Neg; use ptr; use sync::Once; use sys::c; @@ -60,11 +58,26 @@ fn last_error() -> io::Error { io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() }) } +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + /// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) /// and if so, returns the last error from the Windows socket interface. This /// function must be called before another call to the socket API is made. -pub fn cvt>(t: T) -> io::Result { - if t == -T::one() { +pub fn cvt(t: T) -> io::Result { + if t.is_minus_one() { Err(last_error()) } else { Ok(t) @@ -82,7 +95,8 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { /// Just to provide the same interface as sys/unix/net.rs pub fn cvt_r(mut f: F) -> io::Result - where T: One + PartialEq + Neg, F: FnMut() -> T + where T: IsMinusOne, + F: FnMut() -> T { cvt(f()) } diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index 5b0dd256b4c41..c00be91a2d74d 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -17,9 +17,8 @@ pub fn main() { // Bool => does not implement iterator. for i in false..true {} - //~^ ERROR `bool: std::num::One` is not satisfied - //~^^ ERROR `bool: std::iter::Step` is not satisfied - //~^^^ ERROR `for<'a> &'a bool: std::ops::Add` is not satisfied + //~^ ERROR `bool: std::iter::Step` is not satisfied + //~^^ ERROR `for<'a> &'a bool: std::ops::Add` is not satisfied // Unsized type. let arr: &[_] = &[1, 2, 3]; diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index 07233a43b88e2..aaf129e7b8e4a 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -117,11 +117,6 @@ pub fn main() { assert_eq!(nonsense.next(), None); assert_eq!(nonsense, RangeInclusive::Empty { at: 10 }); - // conversion - assert_eq!(0...9, (0..10).into()); - assert_eq!(0...0, (0..1).into()); - assert_eq!(RangeInclusive::Empty { at: 1 }, (1..0).into()); - // output assert_eq!(format!("{:?}", 0...10), "0...10"); assert_eq!(format!("{:?}", ...10), "...10"); diff --git a/src/tools/rustbook/main.rs b/src/tools/rustbook/main.rs index e0092f8e29e73..436dc11975336 100644 --- a/src/tools/rustbook/main.rs +++ b/src/tools/rustbook/main.rs @@ -10,7 +10,6 @@ #![deny(warnings)] -#![feature(iter_arith)] #![feature(rustc_private)] #![feature(rustdoc)] #![feature(question_mark)]