about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2018-05-21 10:45:11 +0200
committerSimon Sapin <simon.sapin@exyr.org>2018-05-22 19:19:09 +0200
commitb825477154e32e8538e00e1e230dadf93bc7e6df (patch)
tree27914379b78147f5b7ed856eaae44d1d0fd2ac98
parentba1363ffe12ac1ac796a620aef2008e4ae6c0477 (diff)
downloadrust-b825477154e32e8538e00e1e230dadf93bc7e6df.tar.gz
rust-b825477154e32e8538e00e1e230dadf93bc7e6df.zip
Remove the unstable Float trait
Following up to #49896 and #50629. Fixes #32110.

E0689 is weird.
-rw-r--r--src/libcore/num/dec2flt/rawfp.rs33
-rw-r--r--src/libcore/num/f32.rs222
-rw-r--r--src/libcore/num/f64.rs228
-rw-r--r--src/libcore/num/mod.rs55
-rw-r--r--src/libcore/tests/num/mod.rs77
-rw-r--r--src/librustc_typeck/diagnostics.rs12
-rw-r--r--src/test/ui/macros/macro-backtrace-invalid-internals.rs4
-rw-r--r--src/test/ui/macros/macro-backtrace-invalid-internals.stderr16
-rw-r--r--src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs8
-rw-r--r--src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr14
10 files changed, 232 insertions, 437 deletions
diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs
index 77180233a23..456d0e956d4 100644
--- a/src/libcore/num/dec2flt/rawfp.rs
+++ b/src/libcore/num/dec2flt/rawfp.rs
@@ -33,7 +33,7 @@ use ops::{Add, Mul, Div, Neg};
 use fmt::{Debug, LowerExp};
 use num::diy_float::Fp;
 use num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
-use num::Float;
+use num::FpCategory;
 use num::dec2flt::num::{self, Big};
 use num::dec2flt::table;
 
@@ -54,24 +54,29 @@ impl Unpacked {
 /// See the parent module's doc comment for why this is necessary.
 ///
 /// Should **never ever** be implemented for other types or be used outside the dec2flt module.
-/// Inherits from `Float` because there is some overlap, but all the reused methods are trivial.
 pub trait RawFloat
-    : Float
-    + Copy
+    : Copy
     + Debug
     + LowerExp
     + Mul<Output=Self>
     + Div<Output=Self>
     + Neg<Output=Self>
-where
-    Self: Float<Bits = <Self as RawFloat>::RawBits>
 {
     const INFINITY: Self;
     const NAN: Self;
     const ZERO: Self;
 
-    /// Same as `Float::Bits` with extra traits.
-    type RawBits: Add<Output = Self::RawBits> + From<u8> + TryFrom<u64>;
+    /// Type used by `to_bits` and `from_bits`.
+    type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
+
+    /// Raw transmutation to integer.
+    fn to_bits(self) -> Self::Bits;
+
+    /// Raw transmutation from integer.
+    fn from_bits(v: Self::Bits) -> Self;
+
+    /// Returns the category that this number falls into.
+    fn classify(self) -> FpCategory;
 
     /// Returns the mantissa, exponent and sign as integers.
     fn integer_decode(self) -> (u64, i16, i8);
@@ -153,7 +158,7 @@ macro_rules! other_constants {
 }
 
 impl RawFloat for f32 {
-    type RawBits = u32;
+    type Bits = u32;
 
     const SIG_BITS: u8 = 24;
     const EXP_BITS: u8 = 8;
@@ -192,11 +197,15 @@ impl RawFloat for f32 {
     fn short_fast_pow10(e: usize) -> Self {
         table::F32_SHORT_POWERS[e]
     }
+
+    fn classify(self) -> FpCategory { self.classify() }
+    fn to_bits(self) -> Self::Bits { self.to_bits() }
+    fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
 }
 
 
 impl RawFloat for f64 {
-    type RawBits = u64;
+    type Bits = u64;
 
     const SIG_BITS: u8 = 53;
     const EXP_BITS: u8 = 11;
@@ -235,6 +244,10 @@ impl RawFloat for f64 {
     fn short_fast_pow10(e: usize) -> Self {
         table::F64_SHORT_POWERS[e]
     }
+
+    fn classify(self) -> FpCategory { self.classify() }
+    fn to_bits(self) -> Self::Bits { self.to_bits() }
+    fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
 }
 
 /// Convert an Fp to the closest machine float type.
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 718dd42a615..e5dbc65cd99 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -18,9 +18,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use mem;
-use num::Float;
 use num::FpCategory;
-use num::FpCategory as Fp;
 
 /// The radix or base of the internal representation of `f32`.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -149,136 +147,9 @@ pub mod consts {
     pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
 }
 
-#[unstable(feature = "core_float",
-           reason = "stable interface is via `impl f{32,64}` in later crates",
-           issue = "32110")]
-impl Float for f32 {
-    type Bits = u32;
-
-    /// Returns `true` if the number is NaN.
-    #[inline]
-    fn is_nan(self) -> bool {
-        self != self
-    }
-
-    /// Returns `true` if the number is infinite.
-    #[inline]
-    fn is_infinite(self) -> bool {
-        self == INFINITY || self == NEG_INFINITY
-    }
-
-    /// Returns `true` if the number is neither infinite or NaN.
-    #[inline]
-    fn is_finite(self) -> bool {
-        !(self.is_nan() || self.is_infinite())
-    }
-
-    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
-    #[inline]
-    fn is_normal(self) -> bool {
-        self.classify() == Fp::Normal
-    }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    fn classify(self) -> Fp {
-        const EXP_MASK: u32 = 0x7f800000;
-        const MAN_MASK: u32 = 0x007fffff;
-
-        let bits = self.to_bits();
-        match (bits & MAN_MASK, bits & EXP_MASK) {
-            (0, 0) => Fp::Zero,
-            (_, 0) => Fp::Subnormal,
-            (0, EXP_MASK) => Fp::Infinite,
-            (_, EXP_MASK) => Fp::Nan,
-            _ => Fp::Normal,
-        }
-    }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    #[inline]
-    fn is_sign_positive(self) -> bool {
-        !self.is_sign_negative()
-    }
-
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
-    #[inline]
-    fn is_sign_negative(self) -> bool {
-        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
-        // applies to zeros and NaNs as well.
-        self.to_bits() & 0x8000_0000 != 0
-    }
-
-    /// Returns the reciprocal (multiplicative inverse) of the number.
-    #[inline]
-    fn recip(self) -> f32 {
-        1.0 / self
-    }
-
-    /// Converts to degrees, assuming the number is in radians.
-    #[inline]
-    fn to_degrees(self) -> f32 {
-        // Use a constant for better precision.
-        const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
-        self * PIS_IN_180
-    }
-
-    /// Converts to radians, assuming the number is in degrees.
-    #[inline]
-    fn to_radians(self) -> f32 {
-        let value: f32 = consts::PI;
-        self * (value / 180.0f32)
-    }
-
-    /// Returns the maximum of the two numbers.
-    #[inline]
-    fn max(self, other: f32) -> f32 {
-        // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
-        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-        // is either x or y, canonicalized (this means results might differ among implementations).
-        // When either x or y is a signalingNaN, then the result is according to 6.2.
-        //
-        // Since we do not support sNaN in Rust yet, we do not need to handle them.
-        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if self.is_nan() || self < other { other } else { self }) * 1.0
-    }
-
-    /// Returns the minimum of the two numbers.
-    #[inline]
-    fn min(self, other: f32) -> f32 {
-        // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
-        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-        // is either x or y, canonicalized (this means results might differ among implementations).
-        // When either x or y is a signalingNaN, then the result is according to 6.2.
-        //
-        // Since we do not support sNaN in Rust yet, we do not need to handle them.
-        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if other.is_nan() || self < other { self } else { other }) * 1.0
-    }
-
-    /// Raw transmutation to `u32`.
-    #[inline]
-    fn to_bits(self) -> u32 {
-        unsafe { mem::transmute(self) }
-    }
-
-    /// Raw transmutation from `u32`.
-    #[inline]
-    fn from_bits(v: u32) -> Self {
-        // It turns out the safety issues with sNaN were overblown! Hooray!
-        unsafe { mem::transmute(v) }
-    }
-}
-
-// FIXME: remove (inline) this macro and the Float trait
-// when updating to a bootstrap compiler that has the new lang items.
-#[unstable(feature = "core_float", issue = "32110")]
-macro_rules! f32_core_methods { () => {
+#[lang = "f32"]
+#[cfg(not(test))]
+impl f32 {
     /// Returns `true` if this value is `NaN` and false otherwise.
     ///
     /// ```
@@ -292,7 +163,9 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_nan(self) -> bool { Float::is_nan(self) }
+    pub fn is_nan(self) -> bool {
+        self != self
+    }
 
     /// Returns `true` if this value is positive infinity or negative infinity and
     /// false otherwise.
@@ -313,7 +186,9 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
+    pub fn is_infinite(self) -> bool {
+        self == INFINITY || self == NEG_INFINITY
+    }
 
     /// Returns `true` if this number is neither infinite nor `NaN`.
     ///
@@ -333,7 +208,9 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_finite(self) -> bool { Float::is_finite(self) }
+    pub fn is_finite(self) -> bool {
+        !(self.is_nan() || self.is_infinite())
+    }
 
     /// Returns `true` if the number is neither zero, infinite,
     /// [subnormal][subnormal], or `NaN`.
@@ -358,7 +235,9 @@ macro_rules! f32_core_methods { () => {
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_normal(self) -> bool { Float::is_normal(self) }
+    pub fn is_normal(self) -> bool {
+        self.classify() == FpCategory::Normal
+    }
 
     /// Returns the floating point category of the number. If only one property
     /// is going to be tested, it is generally faster to use the specific
@@ -375,8 +254,19 @@ macro_rules! f32_core_methods { () => {
     /// assert_eq!(inf.classify(), FpCategory::Infinite);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { Float::classify(self) }
+    pub fn classify(self) -> FpCategory {
+        const EXP_MASK: u32 = 0x7f800000;
+        const MAN_MASK: u32 = 0x007fffff;
+
+        let bits = self.to_bits();
+        match (bits & MAN_MASK, bits & EXP_MASK) {
+            (0, 0) => FpCategory::Zero,
+            (_, 0) => FpCategory::Subnormal,
+            (0, EXP_MASK) => FpCategory::Infinite,
+            (_, EXP_MASK) => FpCategory::Nan,
+            _ => FpCategory::Normal,
+        }
+    }
 
     /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
     /// positive sign bit and positive infinity.
@@ -390,7 +280,9 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
+    pub fn is_sign_positive(self) -> bool {
+        !self.is_sign_negative()
+    }
 
     /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
     /// negative sign bit and negative infinity.
@@ -404,7 +296,11 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
+    pub fn is_sign_negative(self) -> bool {
+        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+        // applies to zeros and NaNs as well.
+        self.to_bits() & 0x8000_0000 != 0
+    }
 
     /// Takes the reciprocal (inverse) of a number, `1/x`.
     ///
@@ -418,7 +314,9 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn recip(self) -> f32 { Float::recip(self) }
+    pub fn recip(self) -> f32 {
+        1.0 / self
+    }
 
     /// Converts radians to degrees.
     ///
@@ -433,7 +331,11 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
     #[inline]
-    pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
+    pub fn to_degrees(self) -> f32 {
+        // Use a constant for better precision.
+        const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
+        self * PIS_IN_180
+    }
 
     /// Converts degrees to radians.
     ///
@@ -448,7 +350,10 @@ macro_rules! f32_core_methods { () => {
     /// ```
     #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
     #[inline]
-    pub fn to_radians(self) -> f32 { Float::to_radians(self) }
+    pub fn to_radians(self) -> f32 {
+        let value: f32 = consts::PI;
+        self * (value / 180.0f32)
+    }
 
     /// Returns the maximum of the two numbers.
     ///
@@ -463,7 +368,15 @@ macro_rules! f32_core_methods { () => {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f32) -> f32 {
-        Float::max(self, other)
+        // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
+        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
+        // is either x or y, canonicalized (this means results might differ among implementations).
+        // When either x or y is a signalingNaN, then the result is according to 6.2.
+        //
+        // Since we do not support sNaN in Rust yet, we do not need to handle them.
+        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
+        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
+        (if self.is_nan() || self < other { other } else { self }) * 1.0
     }
 
     /// Returns the minimum of the two numbers.
@@ -479,7 +392,15 @@ macro_rules! f32_core_methods { () => {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f32) -> f32 {
-        Float::min(self, other)
+        // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
+        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
+        // is either x or y, canonicalized (this means results might differ among implementations).
+        // When either x or y is a signalingNaN, then the result is according to 6.2.
+        //
+        // Since we do not support sNaN in Rust yet, we do not need to handle them.
+        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
+        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
+        (if other.is_nan() || self < other { self } else { other }) * 1.0
     }
 
     /// Raw transmutation to `u32`.
@@ -502,7 +423,7 @@ macro_rules! f32_core_methods { () => {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
     pub fn to_bits(self) -> u32 {
-        Float::to_bits(self)
+        unsafe { mem::transmute(self) }
     }
 
     /// Raw transmutation from `u32`.
@@ -546,12 +467,7 @@ macro_rules! f32_core_methods { () => {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
     pub fn from_bits(v: u32) -> Self {
-        Float::from_bits(v)
+        // It turns out the safety issues with sNaN were overblown! Hooray!
+        unsafe { mem::transmute(v) }
     }
-}}
-
-#[lang = "f32"]
-#[cfg(not(test))]
-impl f32 {
-    f32_core_methods!();
 }
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index f128c55c78a..eb769c4ad5a 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -18,9 +18,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use mem;
-use num::Float;
 use num::FpCategory;
-use num::FpCategory as Fp;
 
 /// The radix or base of the internal representation of `f64`.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -149,135 +147,9 @@ pub mod consts {
     pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
 }
 
-#[unstable(feature = "core_float",
-           reason = "stable interface is via `impl f{32,64}` in later crates",
-           issue = "32110")]
-impl Float for f64 {
-    type Bits = u64;
-
-    /// Returns `true` if the number is NaN.
-    #[inline]
-    fn is_nan(self) -> bool {
-        self != self
-    }
-
-    /// Returns `true` if the number is infinite.
-    #[inline]
-    fn is_infinite(self) -> bool {
-        self == INFINITY || self == NEG_INFINITY
-    }
-
-    /// Returns `true` if the number is neither infinite or NaN.
-    #[inline]
-    fn is_finite(self) -> bool {
-        !(self.is_nan() || self.is_infinite())
-    }
-
-    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
-    #[inline]
-    fn is_normal(self) -> bool {
-        self.classify() == Fp::Normal
-    }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    fn classify(self) -> Fp {
-        const EXP_MASK: u64 = 0x7ff0000000000000;
-        const MAN_MASK: u64 = 0x000fffffffffffff;
-
-        let bits = self.to_bits();
-        match (bits & MAN_MASK, bits & EXP_MASK) {
-            (0, 0) => Fp::Zero,
-            (_, 0) => Fp::Subnormal,
-            (0, EXP_MASK) => Fp::Infinite,
-            (_, EXP_MASK) => Fp::Nan,
-            _ => Fp::Normal,
-        }
-    }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    #[inline]
-    fn is_sign_positive(self) -> bool {
-        !self.is_sign_negative()
-    }
-
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
-    #[inline]
-    fn is_sign_negative(self) -> bool {
-        self.to_bits() & 0x8000_0000_0000_0000 != 0
-    }
-
-    /// Returns the reciprocal (multiplicative inverse) of the number.
-    #[inline]
-    fn recip(self) -> f64 {
-        1.0 / self
-    }
-
-    /// Converts to degrees, assuming the number is in radians.
-    #[inline]
-    fn to_degrees(self) -> f64 {
-        // The division here is correctly rounded with respect to the true
-        // value of 180/π. (This differs from f32, where a constant must be
-        // used to ensure a correctly rounded result.)
-        self * (180.0f64 / consts::PI)
-    }
-
-    /// Converts to radians, assuming the number is in degrees.
-    #[inline]
-    fn to_radians(self) -> f64 {
-        let value: f64 = consts::PI;
-        self * (value / 180.0)
-    }
-
-    /// Returns the maximum of the two numbers.
-    #[inline]
-    fn max(self, other: f64) -> f64 {
-        // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
-        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-        // is either x or y, canonicalized (this means results might differ among implementations).
-        // When either x or y is a signalingNaN, then the result is according to 6.2.
-        //
-        // Since we do not support sNaN in Rust yet, we do not need to handle them.
-        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if self.is_nan() || self < other { other } else { self }) * 1.0
-    }
-
-    /// Returns the minimum of the two numbers.
-    #[inline]
-    fn min(self, other: f64) -> f64 {
-        // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
-        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-        // is either x or y, canonicalized (this means results might differ among implementations).
-        // When either x or y is a signalingNaN, then the result is according to 6.2.
-        //
-        // Since we do not support sNaN in Rust yet, we do not need to handle them.
-        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-        (if other.is_nan() || self < other { self } else { other }) * 1.0
-    }
-
-    /// Raw transmutation to `u64`.
-    #[inline]
-    fn to_bits(self) -> u64 {
-        unsafe { mem::transmute(self) }
-    }
-
-    /// Raw transmutation from `u64`.
-    #[inline]
-    fn from_bits(v: u64) -> Self {
-        // It turns out the safety issues with sNaN were overblown! Hooray!
-        unsafe { mem::transmute(v) }
-    }
-}
-
-// FIXME: remove (inline) this macro and the Float trait
-// when updating to a bootstrap compiler that has the new lang items.
-#[unstable(feature = "core_float", issue = "32110")]
-macro_rules! f64_core_methods { () => {
+#[lang = "f64"]
+#[cfg(not(test))]
+impl f64 {
     /// Returns `true` if this value is `NaN` and false otherwise.
     ///
     /// ```
@@ -291,7 +163,9 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_nan(self) -> bool { Float::is_nan(self) }
+    pub fn is_nan(self) -> bool {
+        self != self
+    }
 
     /// Returns `true` if this value is positive infinity or negative infinity and
     /// false otherwise.
@@ -312,7 +186,9 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
+    pub fn is_infinite(self) -> bool {
+        self == INFINITY || self == NEG_INFINITY
+    }
 
     /// Returns `true` if this number is neither infinite nor `NaN`.
     ///
@@ -332,7 +208,9 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_finite(self) -> bool { Float::is_finite(self) }
+    pub fn is_finite(self) -> bool {
+        !(self.is_nan() || self.is_infinite())
+    }
 
     /// Returns `true` if the number is neither zero, infinite,
     /// [subnormal][subnormal], or `NaN`.
@@ -357,7 +235,9 @@ macro_rules! f64_core_methods { () => {
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_normal(self) -> bool { Float::is_normal(self) }
+    pub fn is_normal(self) -> bool {
+        self.classify() == FpCategory::Normal
+    }
 
     /// Returns the floating point category of the number. If only one property
     /// is going to be tested, it is generally faster to use the specific
@@ -374,8 +254,19 @@ macro_rules! f64_core_methods { () => {
     /// assert_eq!(inf.classify(), FpCategory::Infinite);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { Float::classify(self) }
+    pub fn classify(self) -> FpCategory {
+        const EXP_MASK: u64 = 0x7ff0000000000000;
+        const MAN_MASK: u64 = 0x000fffffffffffff;
+
+        let bits = self.to_bits();
+        match (bits & MAN_MASK, bits & EXP_MASK) {
+            (0, 0) => FpCategory::Zero,
+            (_, 0) => FpCategory::Subnormal,
+            (0, EXP_MASK) => FpCategory::Infinite,
+            (_, EXP_MASK) => FpCategory::Nan,
+            _ => FpCategory::Normal,
+        }
+    }
 
     /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
     /// positive sign bit and positive infinity.
@@ -389,13 +280,17 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
+    pub fn is_sign_positive(self) -> bool {
+        !self.is_sign_negative()
+    }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
     #[inline]
     #[doc(hidden)]
-    pub fn is_positive(self) -> bool { Float::is_sign_positive(self) }
+    pub fn is_positive(self) -> bool {
+        self.is_sign_positive()
+    }
 
     /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
     /// negative sign bit and negative infinity.
@@ -409,13 +304,17 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
+    pub fn is_sign_negative(self) -> bool {
+        self.to_bits() & 0x8000_0000_0000_0000 != 0
+    }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
     #[inline]
     #[doc(hidden)]
-    pub fn is_negative(self) -> bool { Float::is_sign_negative(self) }
+    pub fn is_negative(self) -> bool {
+        self.is_sign_negative()
+    }
 
     /// Takes the reciprocal (inverse) of a number, `1/x`.
     ///
@@ -427,7 +326,9 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn recip(self) -> f64 { Float::recip(self) }
+    pub fn recip(self) -> f64 {
+        1.0 / self
+    }
 
     /// Converts radians to degrees.
     ///
@@ -442,7 +343,12 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
+    pub fn to_degrees(self) -> f64 {
+        // The division here is correctly rounded with respect to the true
+        // value of 180/π. (This differs from f32, where a constant must be
+        // used to ensure a correctly rounded result.)
+        self * (180.0f64 / consts::PI)
+    }
 
     /// Converts degrees to radians.
     ///
@@ -457,7 +363,10 @@ macro_rules! f64_core_methods { () => {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn to_radians(self) -> f64 { Float::to_radians(self) }
+    pub fn to_radians(self) -> f64 {
+        let value: f64 = consts::PI;
+        self * (value / 180.0)
+    }
 
     /// Returns the maximum of the two numbers.
     ///
@@ -472,7 +381,15 @@ macro_rules! f64_core_methods { () => {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f64) -> f64 {
-        Float::max(self, other)
+        // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
+        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
+        // is either x or y, canonicalized (this means results might differ among implementations).
+        // When either x or y is a signalingNaN, then the result is according to 6.2.
+        //
+        // Since we do not support sNaN in Rust yet, we do not need to handle them.
+        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
+        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
+        (if self.is_nan() || self < other { other } else { self }) * 1.0
     }
 
     /// Returns the minimum of the two numbers.
@@ -488,7 +405,15 @@ macro_rules! f64_core_methods { () => {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f64) -> f64 {
-        Float::min(self, other)
+        // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
+        // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
+        // is either x or y, canonicalized (this means results might differ among implementations).
+        // When either x or y is a signalingNaN, then the result is according to 6.2.
+        //
+        // Since we do not support sNaN in Rust yet, we do not need to handle them.
+        // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
+        // multiplying by 1.0. Should switch to the `canonicalize` when it works.
+        (if other.is_nan() || self < other { self } else { other }) * 1.0
     }
 
     /// Raw transmutation to `u64`.
@@ -511,7 +436,7 @@ macro_rules! f64_core_methods { () => {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
     pub fn to_bits(self) -> u64 {
-        Float::to_bits(self)
+        unsafe { mem::transmute(self) }
     }
 
     /// Raw transmutation from `u64`.
@@ -555,12 +480,7 @@ macro_rules! f64_core_methods { () => {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
     pub fn from_bits(v: u64) -> Self {
-        Float::from_bits(v)
+        // It turns out the safety issues with sNaN were overblown! Hooray!
+        unsafe { mem::transmute(v) }
     }
-}}
-
-#[lang = "f64"]
-#[cfg(not(test))]
-impl f64 {
-    f64_core_methods!();
 }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 58d45b107f1..232ecb8fbae 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -4080,61 +4080,6 @@ pub enum FpCategory {
     Normal,
 }
 
-// Technically private and only exposed for coretests:
-#[doc(hidden)]
-#[unstable(feature = "float_internals",
-           reason = "internal routines only exposed for testing",
-           issue = "0")]
-pub trait Float: Sized {
-    /// Type used by `to_bits` and `from_bits`.
-    type Bits;
-
-    /// Returns `true` if this value is NaN and false otherwise.
-    fn is_nan(self) -> bool;
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    fn is_infinite(self) -> bool;
-
-    /// Returns `true` if this number is neither infinite nor NaN.
-    fn is_finite(self) -> bool;
-
-    /// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
-    fn is_normal(self) -> bool;
-
-    /// Returns the category that this number falls into.
-    fn classify(self) -> FpCategory;
-
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
-    fn is_sign_positive(self) -> bool;
-
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
-    fn is_sign_negative(self) -> bool;
-
-    /// Take the reciprocal (inverse) of a number, `1/x`.
-    fn recip(self) -> Self;
-
-    /// Convert radians to degrees.
-    fn to_degrees(self) -> Self;
-
-    /// Convert degrees to radians.
-    fn to_radians(self) -> Self;
-
-    /// Returns the maximum of the two numbers.
-    fn max(self, other: Self) -> Self;
-
-    /// Returns the minimum of the two numbers.
-    fn min(self, other: Self) -> Self;
-
-    /// Raw transmutation to integer.
-    fn to_bits(self) -> Self::Bits;
-
-    /// Raw transmutation from integer.
-    fn from_bits(v: Self::Bits) -> Self;
-}
-
 macro_rules! from_str_radix_int_impl {
     ($($t:ty)*) => {$(
         #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index c7edb55b378..f3439890fce 100644
--- a/src/libcore/tests/num/mod.rs
+++ b/src/libcore/tests/num/mod.rs
@@ -508,51 +508,50 @@ assume_usize_width! {
 
 macro_rules! test_float {
     ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname {
-        use core::num::Float;
         // FIXME(nagisa): these tests should test for sign of -0.0
         #[test]
         fn min() {
-            assert_eq!(0.0.min(0.0), 0.0);
-            assert_eq!((-0.0).min(-0.0), -0.0);
-            assert_eq!(9.0.min(9.0), 9.0);
-            assert_eq!((-9.0).min(0.0), -9.0);
-            assert_eq!(0.0.min(9.0), 0.0);
-            assert_eq!((-0.0).min(-9.0), -9.0);
-            assert_eq!($inf.min(9.0), 9.0);
-            assert_eq!(9.0.min($inf), 9.0);
-            assert_eq!($inf.min(-9.0), -9.0);
-            assert_eq!((-9.0).min($inf), -9.0);
-            assert_eq!($neginf.min(9.0), $neginf);
-            assert_eq!(9.0.min($neginf), $neginf);
-            assert_eq!($neginf.min(-9.0), $neginf);
-            assert_eq!((-9.0).min($neginf), $neginf);
-            assert_eq!($nan.min(9.0), 9.0);
-            assert_eq!($nan.min(-9.0), -9.0);
-            assert_eq!(9.0.min($nan), 9.0);
-            assert_eq!((-9.0).min($nan), -9.0);
-            assert!($nan.min($nan).is_nan());
+            assert_eq!((0.0 as $fty).min(0.0), 0.0);
+            assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
+            assert_eq!((9.0 as $fty).min(9.0), 9.0);
+            assert_eq!((-9.0 as $fty).min(0.0), -9.0);
+            assert_eq!((0.0 as $fty).min(9.0), 0.0);
+            assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
+            assert_eq!(($inf as $fty).min(9.0), 9.0);
+            assert_eq!((9.0 as $fty).min($inf), 9.0);
+            assert_eq!(($inf as $fty).min(-9.0), -9.0);
+            assert_eq!((-9.0 as $fty).min($inf), -9.0);
+            assert_eq!(($neginf as $fty).min(9.0), $neginf);
+            assert_eq!((9.0 as $fty).min($neginf), $neginf);
+            assert_eq!(($neginf as $fty).min(-9.0), $neginf);
+            assert_eq!((-9.0 as $fty).min($neginf), $neginf);
+            assert_eq!(($nan as $fty).min(9.0), 9.0);
+            assert_eq!(($nan as $fty).min(-9.0), -9.0);
+            assert_eq!((9.0 as $fty).min($nan), 9.0);
+            assert_eq!((-9.0 as $fty).min($nan), -9.0);
+            assert!(($nan as $fty).min($nan).is_nan());
         }
         #[test]
         fn max() {
-            assert_eq!(0.0.max(0.0), 0.0);
-            assert_eq!((-0.0).max(-0.0), -0.0);
-            assert_eq!(9.0.max(9.0), 9.0);
-            assert_eq!((-9.0).max(0.0), 0.0);
-            assert_eq!(0.0.max(9.0), 9.0);
-            assert_eq!((-0.0).max(-9.0), -0.0);
-            assert_eq!($inf.max(9.0), $inf);
-            assert_eq!(9.0.max($inf), $inf);
-            assert_eq!($inf.max(-9.0), $inf);
-            assert_eq!((-9.0).max($inf), $inf);
-            assert_eq!($neginf.max(9.0), 9.0);
-            assert_eq!(9.0.max($neginf), 9.0);
-            assert_eq!($neginf.max(-9.0), -9.0);
-            assert_eq!((-9.0).max($neginf), -9.0);
-            assert_eq!($nan.max(9.0), 9.0);
-            assert_eq!($nan.max(-9.0), -9.0);
-            assert_eq!(9.0.max($nan), 9.0);
-            assert_eq!((-9.0).max($nan), -9.0);
-            assert!($nan.max($nan).is_nan());
+            assert_eq!((0.0 as $fty).max(0.0), 0.0);
+            assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
+            assert_eq!((9.0 as $fty).max(9.0), 9.0);
+            assert_eq!((-9.0 as $fty).max(0.0), 0.0);
+            assert_eq!((0.0 as $fty).max(9.0), 9.0);
+            assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
+            assert_eq!(($inf as $fty).max(9.0), $inf);
+            assert_eq!((9.0 as $fty).max($inf), $inf);
+            assert_eq!(($inf as $fty).max(-9.0), $inf);
+            assert_eq!((-9.0 as $fty).max($inf), $inf);
+            assert_eq!(($neginf as $fty).max(9.0), 9.0);
+            assert_eq!((9.0 as $fty).max($neginf), 9.0);
+            assert_eq!(($neginf as $fty).max(-9.0), -9.0);
+            assert_eq!((-9.0 as $fty).max($neginf), -9.0);
+            assert_eq!(($nan as $fty).max(9.0), 9.0);
+            assert_eq!(($nan as $fty).max(-9.0), -9.0);
+            assert_eq!((9.0 as $fty).max($nan), 9.0);
+            assert_eq!((-9.0 as $fty).max($nan), -9.0);
+            assert!(($nan as $fty).max($nan).is_nan());
         }
     } }
 }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 7a572bbbffd..e6a66cd613e 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4552,23 +4552,25 @@ but the type of the numeric value or binding could not be identified.
 The error happens on numeric literals:
 
 ```compile_fail,E0689
-2.0.recip();
+2.0.neg();
 ```
 
 and on numeric bindings without an identified concrete type:
 
 ```compile_fail,E0689
 let x = 2.0;
-x.recip();  // same error as above
+x.neg();  // same error as above
 ```
 
 Because of this, you must give the numeric literal or binding a type:
 
 ```
-let _ = 2.0_f32.recip();
+use std::ops::Neg;
+
+let _ = 2.0_f32.neg();
 let x: f32 = 2.0;
-let _ = x.recip();
-let _ = (2.0 as f32).recip();
+let _ = x.neg();
+let _ = (2.0 as f32).neg();
 ```
 "##,
 
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.rs b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
index 090ff817eb0..0bc2dd5a601 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.rs
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
@@ -48,13 +48,13 @@ macro_rules! fake_anon_field_expr {
 
 macro_rules! real_method_stmt {
      () => {
-          2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+          2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
      }
 }
 
 macro_rules! real_method_expr {
      () => {
-          2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+          2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
      }
 }
 
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
index 284960d2f6e..ec8eee65739 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
@@ -25,17 +25,17 @@ LL |           (1).0 //~ ERROR doesn't have fields
 LL |     fake_anon_field_stmt!();
    |     ------------------------ in this macro invocation
 
-error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
   --> $DIR/macro-backtrace-invalid-internals.rs:51:15
    |
-LL |           2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
-   |               ^^^^^
+LL |           2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+   |               ^^^
 ...
 LL |     real_method_stmt!();
    |     -------------------- in this macro invocation
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |           2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+LL |           2.0_f32.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
    |           ^^^^^^^
 
 error[E0599]: no method named `fake` found for type `{integer}` in the current scope
@@ -65,17 +65,17 @@ LL |           (1).0 //~ ERROR doesn't have fields
 LL |     let _ = fake_anon_field_expr!();
    |             ----------------------- in this macro invocation
 
-error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
   --> $DIR/macro-backtrace-invalid-internals.rs:57:15
    |
-LL |           2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
-   |               ^^^^^
+LL |           2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+   |               ^^^
 ...
 LL |     let _ = real_method_expr!();
    |             ------------------- in this macro invocation
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |           2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+LL |           2.0_f32.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}`
    |           ^^^^^^^
 
 error: aborting due to 8 previous errors
diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
index 2e452f9671f..9bf74c3875f 100644
--- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
+++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 fn main() {
-    let x = 2.0.recip();
-    //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+    let x = 2.0.neg();
+    //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
     let y = 2.0;
-    let x = y.recip();
-    //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+    let x = y.neg();
+    //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
     println!("{:?}", x);
 }
diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
index 477b4c3821d..68c8be7dff8 100644
--- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
+++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
@@ -1,18 +1,18 @@
-error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
    |
-LL |     let x = 2.0.recip();
-   |                 ^^^^^
+LL |     let x = 2.0.neg();
+   |                 ^^^
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |     let x = 2.0_f32.recip();
+LL |     let x = 2.0_f32.neg();
    |             ^^^^^^^
 
-error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
    |
-LL |     let x = y.recip();
-   |               ^^^^^
+LL |     let x = y.neg();
+   |               ^^^
 help: you must specify a type for this binding, like `f32`
    |
 LL |     let y: f32 = 2.0;