From f202a0ba60376e3f0ad24eeedb8b42508e472014 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Tue, 7 Sep 2021 18:46:49 +0200 Subject: [PATCH 01/11] Added next_up and next_down for f32/f64. --- library/core/src/num/f32.rs | 98 ++++++++++++++++++++++++++++++++++++ library/core/src/num/f64.rs | 98 ++++++++++++++++++++++++++++++++++++ library/std/src/f32/tests.rs | 63 +++++++++++++++++++++++ library/std/src/f64/tests.rs | 63 +++++++++++++++++++++++ library/std/src/lib.rs | 1 + 5 files changed, 323 insertions(+) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 83a922ae34891..c5a23d4927d55 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -620,6 +620,104 @@ impl f32 { self.to_bits() & 0x8000_0000 != 0 } + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f32`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// // f32::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f32.next_up() < 0.1 + f32::EPSILON); + /// assert_eq!(16777216f32.next_up(), 16777218.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_up(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const TINY_BITS: u32 = 0x1; // Smallest positive f32. + const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f32`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// let x = 1.0f32; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f32.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_down(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const NEG_TINY_BITS: u32 = 0x8000_0001; // Smallest (in magnitude) negative f32. + const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + /// Takes the reciprocal (inverse) of a number, `1/x`. /// /// ``` diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 4267260eea38c..db09c8bb2430f 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -635,6 +635,104 @@ impl f64 { self.is_sign_negative() } + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f64`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// // f64::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f64.next_up() < 0.1 + f64::EPSILON); + /// assert_eq!(9007199254740992f64.next_up(), 9007199254740994.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_up(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const TINY_BITS: u64 = 0x1; // Smallest positive f64. + const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f64`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// let x = 1.0f64; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f64.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_down(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const NEG_TINY_BITS: u64 = 0x8000_0000_0000_0001; // Smallest (in magnitude) negative f64. + const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + /// Takes the reciprocal (inverse) of a number, `1/x`. /// /// ``` diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 0d4b865f3392a..bc2adfc2f96dd 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -287,6 +287,69 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } +#[test] +fn test_next_up() { + let tiny = f32::from_bits(1); + let tiny_up = f32::from_bits(2); + let max_down = f32::from_bits(0x7f7f_fffe); + let largest_subnormal = f32::from_bits(0x007f_ffff); + let smallest_normal = f32::from_bits(0x0080_0000); + + // Check that NaNs roundtrip. + let nan0 = f32::NAN.to_bits(); + let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; + let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; + assert_eq!(f32::from_bits(nan0).next_up().to_bits(), nan0); + assert_eq!(f32::from_bits(nan1).next_up().to_bits(), nan1); + assert_eq!(f32::from_bits(nan2).next_up().to_bits(), nan2); + + assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); + assert_eq!(f32::MIN.next_up(), -max_down); + assert_eq!((-1.0 - f32::EPSILON).next_up(), -1.0); + assert_eq!((-smallest_normal).next_up(), -largest_subnormal); + assert_eq!((-tiny_up).next_up(), -tiny); + assert_eq!((-tiny).next_up().to_bits(), (-0.0f32).to_bits()); + assert_eq!((-0.0f32).next_up(), tiny); + assert_eq!(0.0f32.next_up(), tiny); + assert_eq!(tiny.next_up(), tiny_up); + assert_eq!(largest_subnormal.next_up(), smallest_normal); + assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON); + assert_eq!(f32::MAX.next_up(), f32::INFINITY); + assert_eq!(f32::INFINITY.next_up(), f32::INFINITY); +} + +#[test] +fn test_next_down() { + let tiny = f32::from_bits(1); + let tiny_up = f32::from_bits(2); + let max_down = f32::from_bits(0x7f7f_fffe); + let largest_subnormal = f32::from_bits(0x007f_ffff); + let smallest_normal = f32::from_bits(0x0080_0000); + + // Check that NaNs roundtrip. + let nan0 = f32::NAN.to_bits(); + let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; + let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; + assert_eq!(f32::from_bits(nan0).next_down().to_bits(), nan0); + assert_eq!(f32::from_bits(nan1).next_down().to_bits(), nan1); + assert_eq!(f32::from_bits(nan2).next_down().to_bits(), nan2); + + assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); + assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); + assert_eq!((-max_down).next_down(), f32::MIN); + assert_eq!((-1.0f32).next_down(), -1.0 - f32::EPSILON); + assert_eq!((-largest_subnormal).next_down(), -smallest_normal); + assert_eq!((-tiny).next_down(), -tiny_up); + assert_eq!((-0.0f32).next_down(), -tiny); + assert_eq!((0.0f32).next_down(), -tiny); + assert_eq!(tiny.next_down().to_bits(), 0.0f32.to_bits()); + assert_eq!(tiny_up.next_down(), tiny); + assert_eq!(smallest_normal.next_down(), largest_subnormal); + assert_eq!((1.0 + f32::EPSILON).next_down(), 1.0f32); + assert_eq!(f32::MAX.next_down(), max_down); + assert_eq!(f32::INFINITY.next_down(), f32::MAX); +} + #[test] fn test_mul_add() { let nan: f32 = f32::NAN; diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 5c163cfe90e0b..8e172cf4963d2 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -289,6 +289,69 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } +#[test] +fn test_next_up() { + let tiny = f64::from_bits(1); + let tiny_up = f64::from_bits(2); + let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); + let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); + let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); + + // Check that NaNs roundtrip. + let nan0 = f64::NAN.to_bits(); + let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; + let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + assert_eq!(f64::from_bits(nan0).next_up().to_bits(), nan0); + assert_eq!(f64::from_bits(nan1).next_up().to_bits(), nan1); + assert_eq!(f64::from_bits(nan2).next_up().to_bits(), nan2); + + assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); + assert_eq!(f64::MIN.next_up(), -max_down); + assert_eq!((-1.0 - f64::EPSILON).next_up(), -1.0); + assert_eq!((-smallest_normal).next_up(), -largest_subnormal); + assert_eq!((-tiny_up).next_up(), -tiny); + assert_eq!((-tiny).next_up().to_bits(), (-0.0f64).to_bits()); + assert_eq!((-0.0f64).next_up(), tiny); + assert_eq!(0.0f64.next_up(), tiny); + assert_eq!(tiny.next_up(), tiny_up); + assert_eq!(largest_subnormal.next_up(), smallest_normal); + assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); + assert_eq!(f64::MAX.next_up(), f64::INFINITY); + assert_eq!(f64::INFINITY.next_up(), f64::INFINITY); +} + +#[test] +fn test_next_down() { + let tiny = f64::from_bits(1); + let tiny_up = f64::from_bits(2); + let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); + let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); + let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); + + // Check that NaNs roundtrip. + let nan0 = f64::NAN.to_bits(); + let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; + let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + assert_eq!(f64::from_bits(nan0).next_down().to_bits(), nan0); + assert_eq!(f64::from_bits(nan1).next_down().to_bits(), nan1); + assert_eq!(f64::from_bits(nan2).next_down().to_bits(), nan2); + + assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); + assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); + assert_eq!((-max_down).next_down(), f64::MIN); + assert_eq!((-1.0f64).next_down(), -1.0 - f64::EPSILON); + assert_eq!((-largest_subnormal).next_down(), -smallest_normal); + assert_eq!((-tiny).next_down(), -tiny_up); + assert_eq!((-0.0f64).next_down(), -tiny); + assert_eq!((0.0f64).next_down(), -tiny); + assert_eq!(tiny.next_down().to_bits(), 0.0f64.to_bits()); + assert_eq!(tiny_up.next_down(), tiny); + assert_eq!(smallest_normal.next_down(), largest_subnormal); + assert_eq!((1.0 + f64::EPSILON).next_down(), 1.0f64); + assert_eq!(f64::MAX.next_down(), max_down); + assert_eq!(f64::INFINITY.next_down(), f64::MAX); +} + #[test] fn test_mul_add() { let nan: f64 = f64::NAN; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c2243b259538a..1f7a421673ded 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -285,6 +285,7 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] +#![feature(float_next_up_down)] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] From 6f543eef359f72bee7797073d417b8857268cb17 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 30 Oct 2021 09:25:04 +0200 Subject: [PATCH 02/11] Fixed float next_up/down 32-bit x87 float NaN roundtrip test case. --- library/std/src/f32/tests.rs | 24 ++++++++++++------------ library/std/src/f64/tests.rs | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index bc2adfc2f96dd..938fd34d84f62 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -296,12 +296,12 @@ fn test_next_up() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - let nan0 = f32::NAN.to_bits(); - let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; - let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; - assert_eq!(f32::from_bits(nan0).next_up().to_bits(), nan0); - assert_eq!(f32::from_bits(nan1).next_up().to_bits(), nan1); - assert_eq!(f32::from_bits(nan2).next_up().to_bits(), nan2); + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_eq!(f32::MIN.next_up(), -max_down); @@ -327,12 +327,12 @@ fn test_next_down() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - let nan0 = f32::NAN.to_bits(); - let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; - let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; - assert_eq!(f32::from_bits(nan0).next_down().to_bits(), nan0); - assert_eq!(f32::from_bits(nan1).next_down().to_bits(), nan1); - assert_eq!(f32::from_bits(nan2).next_down().to_bits(), nan2); + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 8e172cf4963d2..cf46ffcffcf2e 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -298,12 +298,12 @@ fn test_next_up() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - let nan0 = f64::NAN.to_bits(); - let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; - let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; - assert_eq!(f64::from_bits(nan0).next_up().to_bits(), nan0); - assert_eq!(f64::from_bits(nan1).next_up().to_bits(), nan1); - assert_eq!(f64::from_bits(nan2).next_up().to_bits(), nan2); + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_eq!(f64::MIN.next_up(), -max_down); @@ -329,12 +329,12 @@ fn test_next_down() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - let nan0 = f64::NAN.to_bits(); - let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; - let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; - assert_eq!(f64::from_bits(nan0).next_down().to_bits(), nan0); - assert_eq!(f64::from_bits(nan1).next_down().to_bits(), nan1); - assert_eq!(f64::from_bits(nan2).next_down().to_bits(), nan2); + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); From c4e0622869188fd94e0f1f455260ad8098cc1d06 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Mon, 29 Nov 2021 12:10:09 +0100 Subject: [PATCH 03/11] Ensure NaN references values go through function boundary for next_up/down. --- library/std/src/f32/tests.rs | 24 ++++++++++++++++++------ library/std/src/f64/tests.rs | 24 ++++++++++++++++++------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 938fd34d84f62..f748c2a38feb8 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -296,12 +296,18 @@ fn test_next_up() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f32) -> f32 { + crate::hint::black_box(x) + } let nan0 = f32::NAN; let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_eq!(f32::MIN.next_up(), -max_down); @@ -327,12 +333,18 @@ fn test_next_down() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f32) -> f32 { + crate::hint::black_box(x) + } let nan0 = f32::NAN; let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index cf46ffcffcf2e..2524bfe8b9988 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -298,12 +298,18 @@ fn test_next_up() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f64) -> f64 { + crate::hint::black_box(x) + } let nan0 = f64::NAN; let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_eq!(f64::MIN.next_up(), -max_down); @@ -329,12 +335,18 @@ fn test_next_down() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f64) -> f64 { + crate::hint::black_box(x) + } let nan0 = f64::NAN; let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); From f020ba45125c0b69cb4d729003a1e371583107f0 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Tue, 30 Nov 2021 20:54:12 +0100 Subject: [PATCH 04/11] Added tracking issue numbers for float_next_up_down. --- library/core/src/num/f32.rs | 6 ++++-- library/core/src/num/f64.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index c5a23d4927d55..aeaba39217206 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -646,7 +646,8 @@ impl f32 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_up(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. @@ -695,7 +696,8 @@ impl f32 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_down(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index db09c8bb2430f..c9e8397fa0d05 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -661,7 +661,8 @@ impl f64 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_up(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. @@ -710,7 +711,8 @@ impl f64 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_down(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. From 1692bcc0c72db6079bd1d58c6cf56c0390e65e00 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Tue, 30 Nov 2021 21:08:37 +0100 Subject: [PATCH 05/11] Conditionally do not compile NaN roundtrip tests on x87 fp. --- library/std/src/f32/tests.rs | 44 ++++++++++++++++++------------------ library/std/src/f64/tests.rs | 44 ++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index f748c2a38feb8..9639dcd2ef1f6 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -296,18 +296,18 @@ fn test_next_up() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f32) -> f32 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); } - let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_eq!(f32::MIN.next_up(), -max_down); @@ -333,18 +333,18 @@ fn test_next_down() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f32) -> f32 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); } - let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 2524bfe8b9988..e545a10c489d0 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -298,18 +298,18 @@ fn test_next_up() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f64) -> f64 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); } - let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_eq!(f64::MIN.next_up(), -max_down); @@ -335,18 +335,18 @@ fn test_next_down() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f64) -> f64 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); } - let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); From e1c9a88152fea67777549d397c17189157f6e6c2 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Sat, 11 Dec 2021 17:07:23 +0100 Subject: [PATCH 06/11] Fix since attribute for const_manually_drop feature const_manually_drop was stabilized in 1.32 as mentioned in https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1320-2019-01-17 --- library/core/src/mem/manually_drop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 20b6453990d75..f577f102e8db2 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -64,7 +64,7 @@ impl ManuallyDrop { /// ``` #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value } @@ -82,7 +82,7 @@ impl ManuallyDrop { /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { slot.value From 85f786cc9c85473166fee1daec2dfc550f46bed8 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Tue, 14 Dec 2021 20:00:59 -0500 Subject: [PATCH 07/11] add `io::Error::other` constructor --- library/std/src/io/error.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index da88c8c9261b4..210a9ec718315 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -417,6 +417,33 @@ impl Error { Self::_new(kind, error.into()) } + /// Creates a new I/O error from an arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. It is a shortcut for [`Error::new`] + /// with [`ErrorKind::Other`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_error_other)] + /// + /// use std::io::Error; + /// + /// // errors can be created from strings + /// let custom_error = Error::other("oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::other(custom_error); + /// ``` + #[unstable(feature = "io_error_other", issue = "91946")] + pub fn other(error: E) -> Error + where + E: Into>, + { + Self::_new(ErrorKind::Other, error.into()) + } + fn _new(kind: ErrorKind, error: Box) -> Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })) } } From a7e48f25bbb76bc894ccadba93bacd6c2004e6ab Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 15 Dec 2021 10:22:03 +0800 Subject: [PATCH 08/11] update stdarch --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index d219ad63c5075..0716b22e90220 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit d219ad63c5075098fc224a57deb4852b9734327d +Subproject commit 0716b22e902207efabe46879cbf28d0189ab7924 From 8cc222253733779b0aa600181e4723e4832771e7 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 15 Dec 2021 04:23:34 +0000 Subject: [PATCH 09/11] ancillary fix dragonfly build --- library/std/src/os/unix/net/ancillary.rs | 18 +++++++++--------- library/std/src/os/unix/net/stream.rs | 4 ++-- library/std/src/sys/unix/net.rs | 17 +++++++++++++++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index a29008140f784..42adec3352924 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -249,46 +249,46 @@ impl SocketCred { #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] #[must_use] pub fn new() -> SocketCred { - SocketCred(libc::cmsgcred { cmsgcred_pid: 0, cmsgcred_uid: 0, cmsgcred_gid: 0 }) + SocketCred(libc::cmsgcred { cmcred_pid: 0, cmcred_uid: 0, cmcred_gid: 0 }) } /// Set the PID. #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_pid(&mut self, pid: libc::pid_t) { - self.0.cmsgcred_pid = pid; + self.0.cmcred_pid = pid; } /// Get the current PID. #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_pid(&self) -> libc::pid_t { - self.0.cmsgcred_pid + self.0.cmcred_pid } /// Set the UID. #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_uid(&mut self, uid: libc::uid_t) { - self.0.cmsgcred_uid = uid; + self.0.cmcred_uid = uid; } /// Get the current UID. #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_uid(&self) -> libc::uid_t { - self.0.cmsgcred_uid + self.0.cmcred_uid } /// Set the GID. #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_gid(&mut self, gid: libc::gid_t) { - self.0.cmsgcred_gid = gid; + self.0.cmcred_gid = gid; } /// Get the current GID. #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_gid(&self) -> libc::gid_t { - self.0.cmsgcred_gid + self.0.cmcred_gid } } @@ -340,7 +340,7 @@ pub enum AncillaryError { #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub enum AncillaryData<'a> { ScmRights(ScmRights<'a>), - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly"))] ScmCredentials(ScmCredentials<'a>), } @@ -363,7 +363,7 @@ impl<'a> AncillaryData<'a> { /// /// `data` must contain a valid control message and the control message must be type of /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDS`. - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly"))] unsafe fn as_credentials(data: &'a [u8]) -> Self { let ancillary_data_iter = AncillaryDataIter::new(data); let scm_credentials = ScmCredentials(ancillary_data_iter); diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 583f861a92535..e8b6a792219ca 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -415,7 +415,7 @@ impl UnixStream { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly"))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -427,7 +427,7 @@ impl UnixStream { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixStream::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly"))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result { self.0.passcred() diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 15d0dbe07fe7e..711169985e3d2 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -408,17 +408,30 @@ impl Socket { Ok(raw != 0) } - #[cfg(any(target_os = "android", target_os = "linux", target_os = "dragonfly",))] + #[cfg(any(target_os = "android", target_os = "linux"))] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int) } - #[cfg(any(target_os = "android", target_os = "linux", target_os = "dragonfly",))] + #[cfg(target_os = "dragonfly")] + pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { + const SO_PASSCRED: libc::c_int = 0x4000; + setsockopt(self, libc::SOL_SOCKET, SO_PASSCRED, passcred as libc::c_int) + } + + #[cfg(any(target_os = "android", target_os = "linux"))] pub fn passcred(&self) -> io::Result { let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED)?; Ok(passcred != 0) } + #[cfg(target_os = "dragonfly")] + pub fn passcred(&self) -> io::Result { + const SO_PASSCRED: libc::c_int = 0x4000; + let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, SO_PASSCRED)?; + Ok(passcred != 0) + } + #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_int; From 0ec734af321a7a011e515a1b3bed56e2119d5817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Wed, 15 Dec 2021 16:16:26 +0200 Subject: [PATCH 10/11] Pull in libdevstat on FreeBSD --- src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index de6b52a5e001c..2f7c57bcdc461 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -53,7 +53,7 @@ files_to_extract=( for lib in c cxxrt gcc_s m thr util; do files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*") done -for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do +for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*") done From 58fd2ffc966385904f6d769625b4b798f9dc4b90 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 15 Dec 2021 18:38:51 +0100 Subject: [PATCH 11/11] link to pref_align_of tracking issue --- library/core/src/intrinsics.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index ad2f6f213dec8..46370f76e7ced 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -811,7 +811,8 @@ extern "rust-intrinsic" { /// The preferred alignment of a type. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")] + /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). + #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")] pub fn pref_align_of() -> usize; /// The size of the referenced value in bytes.