From 259bbfbc3dd5854f8ee3b89f921ac0812e43bb79 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Sun, 18 Sep 2022 10:51:36 +0900 Subject: [PATCH 1/6] Add negation methods for signed non-zero integers. --- library/core/src/num/nonzero.rs | 154 ++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 532a09736a7ac..d8e3c95cc8702 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -721,6 +721,160 @@ macro_rules! nonzero_signed_operations { // SAFETY: absolute value of nonzero cannot yield zero values. unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } } + + /// Returns `true` if `self` is negative and `false` if the + /// number is positive. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(neg_five.is_negative()); + /// assert!(!pos_five.is_negative()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline(always)] + #[unstable(feature = "nonzero_negation_ops", issue = "none")] + pub const fn is_negative(self) -> bool { + self.get().is_negative() + } + + /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); + /// assert_eq!(min.checked_neg(), None); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "none")] + pub const fn checked_neg(self) -> Option<$Ty> { + if let Some(result) = self.get().checked_neg() { + // SAFETY: negation of nonzero cannot yield zero values. + return Some(unsafe { $Ty::new_unchecked(result) }); + } + None + } + + /// Negates self, overflowing if this is equal to the minimum value. + /// + #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); + /// assert_eq!(min.overflowing_neg(), (min, true)); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "none")] + pub const fn overflowing_neg(self) -> ($Ty, bool) { + let (result, overflow) = self.get().overflowing_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + ((unsafe { $Ty::new_unchecked(result) }), overflow) + } + + /// Saturating negation. Computes `-self`, returning `MAX` if + /// `self == i32::MIN` instead of overflowing. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos_five.saturating_neg(), neg_five); + /// assert_eq!(min.saturating_neg(), max); + /// assert_eq!(max.saturating_neg(), min_plus_one); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "none")] + pub const fn saturating_neg(self) -> $Ty { + if let Some(result) = self.checked_neg() { + return result; + } + $Ty::MAX + } + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.wrapping_neg(), neg_five); + /// assert_eq!(min.wrapping_neg(), min); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "none")] + pub const fn wrapping_neg(self) -> $Ty { + let result = self.get().wrapping_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(result) } + } } )+ } From 7f06d513fbbb01af78fae3586114abd9077b930e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Sep 2022 17:33:59 -0700 Subject: [PATCH 2/6] Don't export `__heap_base` and `__data_end` on wasm32-wasi. `__heap_base` and `__data_end` are exported for use by wasm-bindgen, which uses the wasm32-unknown-unknown target. On wasm32-wasi, as a step toward implementing the Canonical ABI, and as an aid to building speicalized WASI API polyfill wrappers, don't export `__heap_base` and `__data_end` on wasm32-wasi. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e0bd7a33f7373..061053ef2ac97 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1320,10 +1320,12 @@ impl<'a> Linker for WasmLd<'a> { // LLD will hide these otherwise-internal symbols since it only exports // symbols explicitly passed via the `--export` flags above and hides all - // others. Various bits and pieces of tooling use this, so be sure these - // symbols make their way out of the linker as well. - self.cmd.arg("--export=__heap_base"); - self.cmd.arg("--export=__data_end"); + // others. Various bits and pieces of wasm32-unknown-unknown tooling use + // this, so be sure these symbols make their way out of the linker as well. + if self.sess.target.os == "unknown" { + self.cmd.arg("--export=__heap_base"); + self.cmd.arg("--export=__data_end"); + } } fn subsystem(&mut self, _subsystem: &str) {} From 284c94257fbf32e62bbe3a8f9e71ecb644763df9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Sep 2022 11:13:51 -0700 Subject: [PATCH 3/6] Don't export `__wasm_init_memory` on WebAssembly. Since #72889, the Rust wasm target doesn't use --passive-segments, so remove the `--export=__wasm_init_memory`. As documented in the [tool-conventions Linking convention], `__wasm_init_memory` is not intended to be exported. [tool-conventions Linking convention]: https://github.com/WebAssembly/tool-conventions/blob/7c064f304858f67ebf22964a84b7e9658e29557a/Linking.md#shared-memory-and-passive-segments --- compiler/rustc_codegen_ssa/src/back/linker.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e0bd7a33f7373..8dd08467c0893 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1180,18 +1180,12 @@ impl<'a> WasmLd<'a> { // sharing memory and instantiating the module multiple times. As a // result if it were exported then we'd just have no sharing. // - // * `--export=__wasm_init_memory` - when using `--passive-segments` the - // linker will synthesize this function, and so we need to make sure - // that our usage of `--export` below won't accidentally cause this - // function to get deleted. - // // * `--export=*tls*` - when `#[thread_local]` symbols are used these // symbols are how the TLS segments are initialized and configured. if sess.target_features.contains(&sym::atomics) { cmd.arg("--shared-memory"); cmd.arg("--max-memory=1073741824"); cmd.arg("--import-memory"); - cmd.arg("--export=__wasm_init_memory"); cmd.arg("--export=__wasm_init_tls"); cmd.arg("--export=__tls_size"); cmd.arg("--export=__tls_align"); From b707eff5cc8780b535b0d2f170fe886f927c5082 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 28 Sep 2022 14:33:56 -0700 Subject: [PATCH 4/6] rustdoc: cut margin-top from first header in docblock Fixes a regression caused by 8846c0853d8687fda0e5f23f6687b03b243980ee, where a header's top margin used to be collapsed, but isn't any more. --- src/librustdoc/html/static/css/rustdoc.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0ea6d9c38b69f..6e0fe9fb48e56 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -138,6 +138,13 @@ h1, h2, h3, h4 { .docblock h3, .docblock h4, h5, h6 { margin: 15px 0 5px 0; } +.docblock > h2:first-child, +.docblock > h3:first-child, +.docblock > h4:first-child, +.docblock > h5:first-child, +.docblock > h6:first-child { + margin-top: 0; +} h1.fqn { margin: 0; padding: 0; From cdae82c5fc7b04fec84062e82feb0f119d526b81 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 29 Sep 2022 07:32:15 +0900 Subject: [PATCH 5/6] nonzero_negation_ops: Set `issue = "102443"`. --- library/core/src/num/nonzero.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d8e3c95cc8702..1e6e1a155ef5d 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -743,7 +743,7 @@ macro_rules! nonzero_signed_operations { /// ``` #[must_use] #[inline(always)] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn is_negative(self) -> bool { self.get().is_negative() } @@ -769,7 +769,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn checked_neg(self) -> Option<$Ty> { if let Some(result) = self.get().checked_neg() { // SAFETY: negation of nonzero cannot yield zero values. @@ -802,7 +802,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn overflowing_neg(self) -> ($Ty, bool) { let (result, overflow) = self.get().overflowing_neg(); // SAFETY: negation of nonzero cannot yield zero values. @@ -836,7 +836,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn saturating_neg(self) -> $Ty { if let Some(result) = self.checked_neg() { return result; @@ -869,7 +869,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn wrapping_neg(self) -> $Ty { let result = self.get().wrapping_neg(); // SAFETY: negation of nonzero cannot yield zero values. From ceb53a3c4fa9f0c3da7b7e6d24011dee1d15ad09 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 29 Sep 2022 07:33:05 +0900 Subject: [PATCH 6/6] nonzero_negation_ops: `inline(always)` -> `inline`. --- library/core/src/num/nonzero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1e6e1a155ef5d..da402d66502a6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -742,7 +742,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[must_use] - #[inline(always)] + #[inline] #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn is_negative(self) -> bool { self.get().is_negative()