From 6b02362b32271e90894ede6bfd94909bd1c0b229 Mon Sep 17 00:00:00 2001 From: Kyle Strand Date: Sat, 24 Aug 2019 14:58:01 -0700 Subject: Add 'must_use' to all functions 'fn(float) -> float' --- src/libstd/f32.rs | 28 ++++++++++++++++++++++++++++ src/libstd/f64.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index e55afc2344f..d0c64243ee3 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -40,6 +40,7 @@ impl f32 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn floor(self) -> f32 { @@ -73,6 +74,7 @@ impl f32 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ceil(self) -> f32 { @@ -95,6 +97,7 @@ impl f32 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn round(self) -> f32 { @@ -114,6 +117,7 @@ impl f32 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn trunc(self) -> f32 { @@ -135,6 +139,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn fract(self) -> f32 { self - self.trunc() } @@ -158,6 +163,7 @@ impl f32 { /// /// assert!(f32::NAN.abs().is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn abs(self) -> f32 { @@ -182,6 +188,7 @@ impl f32 { /// /// assert!(f32::NAN.signum().is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn signum(self) -> f32 { @@ -367,6 +374,7 @@ impl f32 { /// assert!(abs_difference <= f32::EPSILON); /// assert!(negative.sqrt().is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sqrt(self) -> f32 { @@ -393,6 +401,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f32 { @@ -417,6 +426,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f32 { @@ -439,6 +449,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f32 { @@ -485,6 +496,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f32 { @@ -508,6 +520,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f32 { @@ -565,6 +578,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f32 { @@ -606,6 +620,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f32 { @@ -629,6 +644,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f32 { @@ -651,6 +667,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f32 { @@ -673,6 +690,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f32 { @@ -695,6 +713,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f32 { @@ -716,6 +735,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f32 { @@ -794,6 +814,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f32 { @@ -815,6 +836,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f32 { @@ -838,6 +860,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f32 { @@ -861,6 +884,7 @@ impl f32 { /// // Same result /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f32 { @@ -884,6 +908,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f32 { @@ -904,6 +929,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { @@ -928,6 +954,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { @@ -951,6 +978,7 @@ impl f32 { /// /// assert!(abs_difference <= 1e-5); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atanh(self) -> f32 { diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index b3571026300..0878cfd68b4 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -40,6 +40,7 @@ impl f64 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn floor(self) -> f64 { @@ -57,6 +58,7 @@ impl f64 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ceil(self) -> f64 { @@ -75,6 +77,7 @@ impl f64 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn round(self) -> f64 { @@ -94,6 +97,7 @@ impl f64 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn trunc(self) -> f64 { @@ -113,6 +117,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn fract(self) -> f64 { self - self.trunc() } @@ -136,6 +141,7 @@ impl f64 { /// /// assert!(f64::NAN.abs().is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn abs(self) -> f64 { @@ -160,6 +166,7 @@ impl f64 { /// /// assert!(f64::NAN.signum().is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn signum(self) -> f64 { @@ -332,6 +339,7 @@ impl f64 { /// assert!(abs_difference < 1e-10); /// assert!(negative.sqrt().is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sqrt(self) -> f64 { @@ -356,6 +364,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f64 { @@ -374,6 +383,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f64 { @@ -394,6 +404,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f64 { @@ -432,6 +443,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f64 { @@ -455,6 +467,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f64 { @@ -504,6 +517,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f64 { @@ -543,6 +557,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f64 { @@ -562,6 +577,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f64 { @@ -580,6 +596,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-14); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f64 { @@ -602,6 +619,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f64 { @@ -624,6 +642,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f64 { @@ -643,6 +662,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f64 { @@ -719,6 +739,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f64 { @@ -740,6 +761,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f64 { @@ -763,6 +785,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f64 { @@ -786,6 +809,7 @@ impl f64 { /// // Same result /// assert!(abs_difference < 1.0e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f64 { @@ -809,6 +833,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f64 { @@ -827,6 +852,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { @@ -849,6 +875,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { @@ -872,6 +899,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atanh(self) -> f64 { -- cgit 1.4.1-3-g733a5 From ba2a1fa898c4af38469f4861392defcfb1da00bb Mon Sep 17 00:00:00 2001 From: Kyle Strand Date: Wed, 28 Aug 2019 09:37:52 -0600 Subject: Add reason for each 'must_use' --- src/libstd/f32.rs | 58 +++++++++++++++++++++++++++---------------------------- src/libstd/f64.rs | 58 +++++++++++++++++++++++++++---------------------------- 2 files changed, 58 insertions(+), 58 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index d0c64243ee3..3c08b254466 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -40,7 +40,7 @@ impl f32 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn floor(self) -> f32 { @@ -74,7 +74,7 @@ impl f32 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ceil(self) -> f32 { @@ -97,7 +97,7 @@ impl f32 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn round(self) -> f32 { @@ -117,7 +117,7 @@ impl f32 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn trunc(self) -> f32 { @@ -139,7 +139,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn fract(self) -> f32 { self - self.trunc() } @@ -163,7 +163,7 @@ impl f32 { /// /// assert!(f32::NAN.abs().is_nan()); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn abs(self) -> f32 { @@ -188,7 +188,7 @@ impl f32 { /// /// assert!(f32::NAN.signum().is_nan()); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn signum(self) -> f32 { @@ -221,7 +221,7 @@ impl f32 { /// assert!(f32::NAN.copysign(1.0).is_nan()); /// ``` #[inline] - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] pub fn copysign(self, sign: f32) -> f32 { unsafe { intrinsics::copysignf32(self, sign) } @@ -374,7 +374,7 @@ impl f32 { /// assert!(abs_difference <= f32::EPSILON); /// assert!(negative.sqrt().is_nan()); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sqrt(self) -> f32 { @@ -401,7 +401,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f32 { @@ -426,7 +426,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f32 { @@ -449,7 +449,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f32 { @@ -496,7 +496,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f32 { @@ -520,7 +520,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f32 { @@ -578,7 +578,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f32 { @@ -620,7 +620,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f32 { @@ -644,7 +644,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f32 { @@ -667,7 +667,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f32 { @@ -690,7 +690,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f32 { @@ -713,7 +713,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f32 { @@ -735,7 +735,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f32 { @@ -814,7 +814,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f32 { @@ -836,7 +836,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f32 { @@ -860,7 +860,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f32 { @@ -884,7 +884,7 @@ impl f32 { /// // Same result /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f32 { @@ -908,7 +908,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f32 { @@ -929,7 +929,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { @@ -954,7 +954,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { @@ -978,7 +978,7 @@ impl f32 { /// /// assert!(abs_difference <= 1e-5); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atanh(self) -> f32 { diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 0878cfd68b4..74c81b47bbb 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -40,7 +40,7 @@ impl f64 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn floor(self) -> f64 { @@ -58,7 +58,7 @@ impl f64 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ceil(self) -> f64 { @@ -77,7 +77,7 @@ impl f64 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn round(self) -> f64 { @@ -97,7 +97,7 @@ impl f64 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn trunc(self) -> f64 { @@ -117,7 +117,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn fract(self) -> f64 { self - self.trunc() } @@ -141,7 +141,7 @@ impl f64 { /// /// assert!(f64::NAN.abs().is_nan()); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn abs(self) -> f64 { @@ -166,7 +166,7 @@ impl f64 { /// /// assert!(f64::NAN.signum().is_nan()); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn signum(self) -> f64 { @@ -199,7 +199,7 @@ impl f64 { /// assert!(f64::NAN.copysign(1.0).is_nan()); /// ``` #[inline] - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] pub fn copysign(self, sign: f64) -> f64 { unsafe { intrinsics::copysignf64(self, sign) } @@ -339,7 +339,7 @@ impl f64 { /// assert!(abs_difference < 1e-10); /// assert!(negative.sqrt().is_nan()); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sqrt(self) -> f64 { @@ -364,7 +364,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f64 { @@ -383,7 +383,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f64 { @@ -404,7 +404,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f64 { @@ -443,7 +443,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f64 { @@ -467,7 +467,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f64 { @@ -517,7 +517,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f64 { @@ -557,7 +557,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f64 { @@ -577,7 +577,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f64 { @@ -596,7 +596,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-14); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f64 { @@ -619,7 +619,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f64 { @@ -642,7 +642,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f64 { @@ -662,7 +662,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f64 { @@ -739,7 +739,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f64 { @@ -761,7 +761,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f64 { @@ -785,7 +785,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f64 { @@ -809,7 +809,7 @@ impl f64 { /// // Same result /// assert!(abs_difference < 1.0e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f64 { @@ -833,7 +833,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f64 { @@ -852,7 +852,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { @@ -875,7 +875,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { @@ -899,7 +899,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[must_use] + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atanh(self) -> f64 { -- cgit 1.4.1-3-g733a5 From c5b0003d9948ac302631f83e2addfa51db6ac601 Mon Sep 17 00:00:00 2001 From: Kyle Strand Date: Wed, 28 Aug 2019 09:41:45 -0600 Subject: Annotate functions taking extra args --- src/libstd/f32.rs | 12 +++++++++++- src/libstd/f64.rs | 11 ++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 3c08b254466..142558a9f0a 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -220,8 +220,8 @@ impl f32 { /// /// assert!(f32::NAN.copysign(1.0).is_nan()); /// ``` - #[inline] #[must_use = "method returns a new number and does not mutate the original value"] + #[inline] #[stable(feature = "copysign", since = "1.35.0")] pub fn copysign(self, sign: f32) -> f32 { unsafe { intrinsics::copysignf32(self, sign) } @@ -247,6 +247,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn mul_add(self, a: f32, b: f32) -> f32 { @@ -270,6 +271,7 @@ impl f32 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] pub fn div_euclid(self, rhs: f32) -> f32 { @@ -303,6 +305,7 @@ impl f32 { /// // limitation due to round-off error /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] pub fn rem_euclid(self, rhs: f32) -> f32 { @@ -329,6 +332,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powi(self, n: i32) -> f32 { @@ -347,6 +351,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powf(self, n: f32) -> f32 { @@ -478,6 +483,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log(self, base: f32) -> f32 { self.ln() / base.ln() } @@ -550,6 +556,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_deprecated(since = "1.10.0", @@ -601,6 +608,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f32) -> f32 { @@ -770,6 +778,7 @@ impl f32 { /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f32) -> f32 { @@ -1006,6 +1015,7 @@ impl f32 { /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0); /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan()); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "clamp", issue = "44095")] #[inline] pub fn clamp(self, min: f32, max: f32) -> f32 { diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 74c81b47bbb..d46cef149f1 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -198,9 +198,9 @@ impl f64 { /// /// assert!(f64::NAN.copysign(1.0).is_nan()); /// ``` - #[inline] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] + #[inline] pub fn copysign(self, sign: f64) -> f64 { unsafe { intrinsics::copysignf64(self, sign) } } @@ -223,6 +223,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn mul_add(self, a: f64, b: f64) -> f64 { @@ -246,6 +247,7 @@ impl f64 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] pub fn div_euclid(self, rhs: f64) -> f64 { @@ -279,6 +281,7 @@ impl f64 { /// // limitation due to round-off error /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] pub fn rem_euclid(self, rhs: f64) -> f64 { @@ -302,6 +305,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powi(self, n: i32) -> f64 { @@ -318,6 +322,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powf(self, n: f64) -> f64 { @@ -427,6 +432,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() } @@ -491,6 +497,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_deprecated(since = "1.10.0", @@ -538,6 +545,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f64) -> f64 { @@ -697,6 +705,7 @@ impl f64 { /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f64) -> f64 { -- cgit 1.4.1-3-g733a5 From 54cb728ab8b89ef31578455031519101a93dadc7 Mon Sep 17 00:00:00 2001 From: Kyle Strand Date: Wed, 28 Aug 2019 12:04:32 -0600 Subject: Let 'clamp' be invoked without using return value; used in tests --- src/libstd/f32.rs | 3 ++- src/libstd/f64.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 142558a9f0a..aefe4690b10 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1015,7 +1015,8 @@ impl f32 { /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0); /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan()); /// ``` - #[must_use = "method returns a new number and does not mutate the original value"] + // The tests below invoke `clamp` without a return value in order to cause a `panic`. + // #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "clamp", issue = "44095")] #[inline] pub fn clamp(self, min: f32, max: f32) -> f32 { diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index d46cef149f1..0eca1434a63 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -936,6 +936,8 @@ impl f64 { /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0); /// assert!((std::f64::NAN).clamp(-2.0, 1.0).is_nan()); /// ``` + // The tests below invoke `clamp` without a return value in order to cause a `panic`. + // #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "clamp", issue = "44095")] #[inline] pub fn clamp(self, min: f64, max: f64) -> f64 { -- cgit 1.4.1-3-g733a5 From 1aa5d0cace3a72ae23f32ece5bb18085b36b5258 Mon Sep 17 00:00:00 2001 From: Kyle Strand Date: Thu, 5 Sep 2019 10:22:11 -0600 Subject: Restore 'must_use' for 'clamp'; fix warning for tests --- src/libstd/f32.rs | 9 ++++----- src/libstd/f64.rs | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index aefe4690b10..72a8f31cec1 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1015,8 +1015,7 @@ impl f32 { /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0); /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan()); /// ``` - // The tests below invoke `clamp` without a return value in order to cause a `panic`. - // #[must_use = "method returns a new number and does not mutate the original value"] + #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "clamp", issue = "44095")] #[inline] pub fn clamp(self, min: f32, max: f32) -> f32 { @@ -1631,18 +1630,18 @@ mod tests { #[test] #[should_panic] fn test_clamp_min_greater_than_max() { - 1.0f32.clamp(3.0, 1.0); + let _ = 1.0f32.clamp(3.0, 1.0); } #[test] #[should_panic] fn test_clamp_min_is_nan() { - 1.0f32.clamp(NAN, 1.0); + let _ = 1.0f32.clamp(NAN, 1.0); } #[test] #[should_panic] fn test_clamp_max_is_nan() { - 1.0f32.clamp(3.0, NAN); + let _ = 1.0f32.clamp(3.0, NAN); } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 0eca1434a63..762a87e2572 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -936,8 +936,7 @@ impl f64 { /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0); /// assert!((std::f64::NAN).clamp(-2.0, 1.0).is_nan()); /// ``` - // The tests below invoke `clamp` without a return value in order to cause a `panic`. - // #[must_use = "method returns a new number and does not mutate the original value"] + #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "clamp", issue = "44095")] #[inline] pub fn clamp(self, min: f64, max: f64) -> f64 { @@ -1571,18 +1570,18 @@ mod tests { #[test] #[should_panic] fn test_clamp_min_greater_than_max() { - 1.0f64.clamp(3.0, 1.0); + let _ = 1.0f64.clamp(3.0, 1.0); } #[test] #[should_panic] fn test_clamp_min_is_nan() { - 1.0f64.clamp(NAN, 1.0); + let _ = 1.0f64.clamp(NAN, 1.0); } #[test] #[should_panic] fn test_clamp_max_is_nan() { - 1.0f64.clamp(3.0, NAN); + let _ = 1.0f64.clamp(3.0, NAN); } } -- cgit 1.4.1-3-g733a5 From 2ab812c18176dece9058d2dc0639a0eeb5f42c7d Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 09:30:35 +0200 Subject: Rename state to state_and_queue --- src/libstd/sync/once.rs | 57 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e28fbca7fa1..277ea954c56 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -78,9 +78,9 @@ use crate::thread::{self, Thread}; /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct Once { - // This `state` word is actually an encoded version of just a pointer to a - // `Waiter`, so we add the `PhantomData` appropriately. - state: AtomicUsize, + // `state_and_queue` is actually an a pointer to a `Waiter` with extra state + // bits, so we add the `PhantomData` appropriately. + state_and_queue: AtomicUsize, _marker: marker::PhantomData<*mut Waiter>, } @@ -121,8 +121,8 @@ pub struct OnceState { )] pub const ONCE_INIT: Once = Once::new(); -// Four states that a Once can be in, encoded into the lower bits of `state` in -// the Once structure. +// Four states that a Once can be in, encoded into the lower bits of +// `state_and_queue` in the Once structure. const INCOMPLETE: usize = 0x0; const POISONED: usize = 0x1; const RUNNING: usize = 0x2; @@ -151,7 +151,7 @@ impl Once { #[stable(feature = "once_new", since = "1.2.0")] pub const fn new() -> Once { Once { - state: AtomicUsize::new(INCOMPLETE), + state_and_queue: AtomicUsize::new(INCOMPLETE), _marker: marker::PhantomData, } } @@ -330,7 +330,7 @@ impl Once { // operations visible to us, and, this being a fast path, weaker // ordering helps with performance. This `Acquire` synchronizes with // `SeqCst` operations on the slow path. - self.state.load(Ordering::Acquire) == COMPLETE + self.state_and_queue.load(Ordering::Acquire) == COMPLETE } // This is a non-generic function to reduce the monomorphization cost of @@ -352,10 +352,10 @@ impl Once { // This cold path uses SeqCst consistently because the // performance difference really does not matter there, and // SeqCst minimizes the chances of something going wrong. - let mut state = self.state.load(Ordering::SeqCst); + let mut state_and_queue = self.state_and_queue.load(Ordering::SeqCst); 'outer: loop { - match state { + match state_and_queue { // If we're complete, then there's nothing to do, we just // jettison out as we shouldn't run the closure. COMPLETE => return, @@ -372,10 +372,11 @@ impl Once { // bits). POISONED | INCOMPLETE => { - let old = self.state.compare_and_swap(state, RUNNING, - Ordering::SeqCst); - if old != state { - state = old; + let old = self.state_and_queue.compare_and_swap(state_and_queue, + RUNNING, + Ordering::SeqCst); + if old != state_and_queue { + state_and_queue = old; continue } @@ -388,7 +389,7 @@ impl Once { panicked: true, me: self, }; - init(state == POISONED); + init(state_and_queue == POISONED); complete.panicked = false; return } @@ -399,7 +400,7 @@ impl Once { // head of the list and bail out if we ever see a state that's // not RUNNING. _ => { - assert!(state & STATE_MASK == RUNNING); + assert!(state_and_queue & STATE_MASK == RUNNING); let mut node = Waiter { thread: Some(thread::current()), signaled: AtomicBool::new(false), @@ -408,13 +409,13 @@ impl Once { let me = &mut node as *mut Waiter as usize; assert!(me & STATE_MASK == 0); - while state & STATE_MASK == RUNNING { - node.next = (state & !STATE_MASK) as *mut Waiter; - let old = self.state.compare_and_swap(state, - me | RUNNING, - Ordering::SeqCst); - if old != state { - state = old; + while state_and_queue & STATE_MASK == RUNNING { + node.next = (state_and_queue & !STATE_MASK) as *mut Waiter; + let old = self.state_and_queue.compare_and_swap(state_and_queue, + me | RUNNING, + Ordering::SeqCst); + if old != state_and_queue { + state_and_queue = old; continue } @@ -424,7 +425,7 @@ impl Once { while !node.signaled.load(Ordering::SeqCst) { thread::park(); } - state = self.state.load(Ordering::SeqCst); + state_and_queue = self.state_and_queue.load(Ordering::SeqCst); continue 'outer } } @@ -444,19 +445,19 @@ impl Drop for Finish<'_> { fn drop(&mut self) { // Swap out our state with however we finished. We should only ever see // an old state which was RUNNING. - let queue = if self.panicked { - self.me.state.swap(POISONED, Ordering::SeqCst) + let state_and_queue = if self.panicked { + self.me.state_and_queue.swap(POISONED, Ordering::SeqCst) } else { - self.me.state.swap(COMPLETE, Ordering::SeqCst) + self.me.state_and_queue.swap(COMPLETE, Ordering::SeqCst) }; - assert_eq!(queue & STATE_MASK, RUNNING); + assert_eq!(state_and_queue & STATE_MASK, RUNNING); // Decode the RUNNING to a list of waiters, then walk that entire list // and wake them up. Note that it is crucial that after we store `true` // in the node it can be free'd! As a result we load the `thread` to // signal ahead of time and then unpark it after the store. unsafe { - let mut queue = (queue & !STATE_MASK) as *mut Waiter; + let mut queue = (state_and_queue & !STATE_MASK) as *mut Waiter; while !queue.is_null() { let next = (*queue).next; let thread = (*queue).thread.take().unwrap(); -- cgit 1.4.1-3-g733a5 From 7f1e166899a90226480d564549c36a395e2d8f47 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 09:50:32 +0200 Subject: Simplify loop conditions in RUNNING and add comments --- src/libstd/sync/once.rs | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 277ea954c56..7a660daf2cb 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -354,7 +354,7 @@ impl Once { // SeqCst minimizes the chances of something going wrong. let mut state_and_queue = self.state_and_queue.load(Ordering::SeqCst); - 'outer: loop { + loop { match state_and_queue { // If we're complete, then there's nothing to do, we just // jettison out as we shouldn't run the closure. @@ -401,33 +401,45 @@ impl Once { // not RUNNING. _ => { assert!(state_and_queue & STATE_MASK == RUNNING); + // Create the node for our current thread that we are going to try to slot + // in at the head of the linked list. let mut node = Waiter { thread: Some(thread::current()), signaled: AtomicBool::new(false), next: ptr::null_mut(), }; let me = &mut node as *mut Waiter as usize; - assert!(me & STATE_MASK == 0); + assert!(me & STATE_MASK == 0); // We assume pointers have 2 free bits that + // we can use for state. + + // Try to slide in the node at the head of the linked list. + // Run in a loop where we make sure the status is still RUNNING, and that + // another thread did not just replace the head of the linked list. + let mut old_head_and_status = state_and_queue; + loop { + if old_head_and_status & STATE_MASK != RUNNING { + return; // No need anymore to enqueue ourselves. + } - while state_and_queue & STATE_MASK == RUNNING { - node.next = (state_and_queue & !STATE_MASK) as *mut Waiter; - let old = self.state_and_queue.compare_and_swap(state_and_queue, + node.next = (old_head_and_status & !STATE_MASK) as *mut Waiter; + let old = self.state_and_queue.compare_and_swap(old_head_and_status, me | RUNNING, - Ordering::SeqCst); - if old != state_and_queue { - state_and_queue = old; - continue + Ordering::Release); + if old == old_head_and_status { + break; // Success! } + old_head_and_status = old; + } - // Once we've enqueued ourselves, wait in a loop. - // Afterwards reload the state and continue with what we - // were doing from before. - while !node.signaled.load(Ordering::SeqCst) { - thread::park(); - } - state_and_queue = self.state_and_queue.load(Ordering::SeqCst); - continue 'outer + // We have enqueued ourselves, now lets wait. + // It is important not to return before being signaled, otherwise we would + // drop our `Waiter` node and leave a hole in the linked list (and a + // dangling reference). Guard against spurious wakeups by reparking + // ourselves until we are signaled. + while !node.signaled.load(Ordering::SeqCst) { + thread::park(); } + state_and_queue = self.state_and_queue.load(Ordering::SeqCst); } } } -- cgit 1.4.1-3-g733a5 From 1479c22a390a6b95706d4280cd7be24e4410dc77 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 09:56:41 +0200 Subject: Don't mutate waiter nodes --- src/libstd/sync/once.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 7a660daf2cb..d8565e55ab2 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -81,7 +81,7 @@ pub struct Once { // `state_and_queue` is actually an a pointer to a `Waiter` with extra state // bits, so we add the `PhantomData` appropriately. state_and_queue: AtomicUsize, - _marker: marker::PhantomData<*mut Waiter>, + _marker: marker::PhantomData<*const Waiter>, } // The `PhantomData` of a raw pointer removes these two auto traits, but we @@ -134,9 +134,9 @@ const STATE_MASK: usize = 0x3; // Representation of a node in the linked list of waiters in the RUNNING state. struct Waiter { - thread: Option, + thread: Thread, signaled: AtomicBool, - next: *mut Waiter, + next: *const Waiter, } // Helper struct used to clean up after a closure call with a `Drop` @@ -404,11 +404,11 @@ impl Once { // Create the node for our current thread that we are going to try to slot // in at the head of the linked list. let mut node = Waiter { - thread: Some(thread::current()), + thread: thread::current(), signaled: AtomicBool::new(false), - next: ptr::null_mut(), + next: ptr::null(), }; - let me = &mut node as *mut Waiter as usize; + let me = &node as *const Waiter as usize; assert!(me & STATE_MASK == 0); // We assume pointers have 2 free bits that // we can use for state. @@ -421,7 +421,7 @@ impl Once { return; // No need anymore to enqueue ourselves. } - node.next = (old_head_and_status & !STATE_MASK) as *mut Waiter; + node.next = (old_head_and_status & !STATE_MASK) as *const Waiter; let old = self.state_and_queue.compare_and_swap(old_head_and_status, me | RUNNING, Ordering::Release); @@ -469,10 +469,10 @@ impl Drop for Finish<'_> { // in the node it can be free'd! As a result we load the `thread` to // signal ahead of time and then unpark it after the store. unsafe { - let mut queue = (state_and_queue & !STATE_MASK) as *mut Waiter; + let mut queue = (state_and_queue & !STATE_MASK) as *const Waiter; while !queue.is_null() { let next = (*queue).next; - let thread = (*queue).thread.take().unwrap(); + let thread = (*queue).thread.clone(); (*queue).signaled.store(true, Ordering::SeqCst); thread.unpark(); queue = next; -- cgit 1.4.1-3-g733a5 From fbc242f1ef172f6fa5b7bc837b5c3a78a4c8f850 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 11:44:31 +0200 Subject: Turn Finish into WaiterQueue --- src/libstd/sync/once.rs | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index d8565e55ab2..01cb7582d38 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -139,13 +139,15 @@ struct Waiter { next: *const Waiter, } -// Helper struct used to clean up after a closure call with a `Drop` -// implementation to also run on panic. -struct Finish<'a> { - panicked: bool, - me: &'a Once, +// Head of a linked list of waiters. +// Every node is a struct on the stack of a waiting thread. +// Will wake up the waiters when it gets dropped, i.e. also on panic. +struct WaiterQueue<'a> { + state_and_queue: &'a AtomicUsize, + set_state_on_drop_to: usize, } + impl Once { /// Creates a new `Once` value. #[stable(feature = "once_new", since = "1.2.0")] @@ -379,18 +381,16 @@ impl Once { state_and_queue = old; continue } - - // Run the initialization routine, letting it know if we're - // poisoned or not. The `Finish` struct is then dropped, and - // the `Drop` implementation here is responsible for waking - // up other waiters both in the normal return and panicking - // case. - let mut complete = Finish { - panicked: true, - me: self, + // `waiter_queue` will manage other waiting threads, and + // wake them up on drop. + let mut waiter_queue = WaiterQueue { + state_and_queue: &self.state_and_queue, + set_state_on_drop_to: POISONED, }; + // Run the initialization function, letting it know if we're + // poisoned or not. init(state_and_queue == POISONED); - complete.panicked = false; + waiter_queue.set_state_on_drop_to = COMPLETE; return } @@ -453,15 +453,13 @@ impl fmt::Debug for Once { } } -impl Drop for Finish<'_> { +impl Drop for WaiterQueue<'_> { fn drop(&mut self) { - // Swap out our state with however we finished. We should only ever see - // an old state which was RUNNING. - let state_and_queue = if self.panicked { - self.me.state_and_queue.swap(POISONED, Ordering::SeqCst) - } else { - self.me.state_and_queue.swap(COMPLETE, Ordering::SeqCst) - }; + // Swap out our state with however we finished. + let state_and_queue = self.state_and_queue.swap(self.set_state_on_drop_to, + Ordering::SeqCst); + + // We should only ever see an old state which was RUNNING. assert_eq!(state_and_queue & STATE_MASK, RUNNING); // Decode the RUNNING to a list of waiters, then walk that entire list -- cgit 1.4.1-3-g733a5 From 2e8eb5f33d55b507da687593bbb7042416d73058 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 10:01:22 +0200 Subject: Move thread parking to a seperate function --- src/libstd/sync/once.rs | 80 ++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 38 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 01cb7582d38..2c09fb3318b 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -401,44 +401,7 @@ impl Once { // not RUNNING. _ => { assert!(state_and_queue & STATE_MASK == RUNNING); - // Create the node for our current thread that we are going to try to slot - // in at the head of the linked list. - let mut node = Waiter { - thread: thread::current(), - signaled: AtomicBool::new(false), - next: ptr::null(), - }; - let me = &node as *const Waiter as usize; - assert!(me & STATE_MASK == 0); // We assume pointers have 2 free bits that - // we can use for state. - - // Try to slide in the node at the head of the linked list. - // Run in a loop where we make sure the status is still RUNNING, and that - // another thread did not just replace the head of the linked list. - let mut old_head_and_status = state_and_queue; - loop { - if old_head_and_status & STATE_MASK != RUNNING { - return; // No need anymore to enqueue ourselves. - } - - node.next = (old_head_and_status & !STATE_MASK) as *const Waiter; - let old = self.state_and_queue.compare_and_swap(old_head_and_status, - me | RUNNING, - Ordering::Release); - if old == old_head_and_status { - break; // Success! - } - old_head_and_status = old; - } - - // We have enqueued ourselves, now lets wait. - // It is important not to return before being signaled, otherwise we would - // drop our `Waiter` node and leave a hole in the linked list (and a - // dangling reference). Guard against spurious wakeups by reparking - // ourselves until we are signaled. - while !node.signaled.load(Ordering::SeqCst) { - thread::park(); - } + wait(&self.state_and_queue, state_and_queue); state_and_queue = self.state_and_queue.load(Ordering::SeqCst); } } @@ -446,6 +409,47 @@ impl Once { } } +fn wait(state_and_queue: &AtomicUsize, current_state: usize) { + // Create the node for our current thread that we are going to try to slot + // in at the head of the linked list. + let mut node = Waiter { + thread: thread::current(), + signaled: AtomicBool::new(false), + next: ptr::null(), + }; + let me = &node as *const Waiter as usize; + assert!(me & STATE_MASK == 0); // We assume pointers have 2 free bits that + // we can use for state. + + // Try to slide in the node at the head of the linked list. + // Run in a loop where we make sure the status is still RUNNING, and that + // another thread did not just replace the head of the linked list. + let mut old_head_and_status = current_state; + loop { + if old_head_and_status & STATE_MASK != RUNNING { + return; // No need anymore to enqueue ourselves. + } + + node.next = (old_head_and_status & !STATE_MASK) as *const Waiter; + let old = state_and_queue.compare_and_swap(old_head_and_status, + me | RUNNING, + Ordering::Release); + if old == old_head_and_status { + break; // Success! + } + old_head_and_status = old; + } + + // We have enqueued ourselves, now lets wait. + // It is important not to return before being signaled, otherwise we would + // drop our `Waiter` node and leave a hole in the linked list (and a + // dangling reference). Guard against spurious wakeups by reparking + // ourselves until we are signaled. + while !node.signaled.load(Ordering::SeqCst) { + thread::park(); + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Once { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -- cgit 1.4.1-3-g733a5 From 4b8da9ccd528d46637c88a40f6cdd0d634c0fb22 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 11:02:20 +0200 Subject: Reduce the amount of comments in call_inner --- src/libstd/sync/once.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 2c09fb3318b..59cc6188045 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -355,25 +355,16 @@ impl Once { // performance difference really does not matter there, and // SeqCst minimizes the chances of something going wrong. let mut state_and_queue = self.state_and_queue.load(Ordering::SeqCst); - loop { match state_and_queue { - // If we're complete, then there's nothing to do, we just - // jettison out as we shouldn't run the closure. - COMPLETE => return, - - // If we're poisoned and we're not in a mode to ignore - // poisoning, then we panic here to propagate the poison. + COMPLETE => break, POISONED if !ignore_poisoning => { + // Panic to propagate the poison. panic!("Once instance has previously been poisoned"); } - - // Otherwise if we see a poisoned or otherwise incomplete state - // we will attempt to move ourselves into the RUNNING state. If - // we succeed, then the queue of waiters starts at null (all 0 - // bits). POISONED | INCOMPLETE => { + // Try to register this thread as the one RUNNING. let old = self.state_and_queue.compare_and_swap(state_and_queue, RUNNING, Ordering::SeqCst); @@ -391,15 +382,11 @@ impl Once { // poisoned or not. init(state_and_queue == POISONED); waiter_queue.set_state_on_drop_to = COMPLETE; - return + break } - - // All other values we find should correspond to the RUNNING - // state with an encoded waiter list in the more significant - // bits. We attempt to enqueue ourselves by moving us to the - // head of the list and bail out if we ever see a state that's - // not RUNNING. _ => { + // All other values must be RUNNING with possibly a + // pointer to the waiter queue in the more significant bits. assert!(state_and_queue & STATE_MASK == RUNNING); wait(&self.state_and_queue, state_and_queue); state_and_queue = self.state_and_queue.load(Ordering::SeqCst); -- cgit 1.4.1-3-g733a5 From 88c70edef66b6885dec6aa8f7a4e73eff2b745ef Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 10:10:36 +0200 Subject: In Waiter use interior mutability for thread --- src/libstd/sync/once.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 59cc6188045..ef8a95eed27 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -52,6 +52,7 @@ // You'll find a few more details in the implementation, but that's the gist of // it! +use crate::cell::Cell; use crate::fmt; use crate::marker; use crate::ptr; @@ -132,9 +133,14 @@ const COMPLETE: usize = 0x3; // this is in the RUNNING state. const STATE_MASK: usize = 0x3; -// Representation of a node in the linked list of waiters in the RUNNING state. +// Representation of a node in the linked list of waiters, used while in the +// RUNNING state. +// Note: `Waiter` can't hold a mutable pointer to the next thread, because then +// `wait` would both hand out a mutable reference to its `Waiter` node, and keep +// a shared reference to check `signaled`. Instead we hold shared references and +// use interior mutability. struct Waiter { - thread: Thread, + thread: Cell>, signaled: AtomicBool, next: *const Waiter, } @@ -400,7 +406,7 @@ fn wait(state_and_queue: &AtomicUsize, current_state: usize) { // Create the node for our current thread that we are going to try to slot // in at the head of the linked list. let mut node = Waiter { - thread: thread::current(), + thread: Cell::new(Some(thread::current())), signaled: AtomicBool::new(false), next: ptr::null(), }; @@ -453,18 +459,22 @@ impl Drop for WaiterQueue<'_> { // We should only ever see an old state which was RUNNING. assert_eq!(state_and_queue & STATE_MASK, RUNNING); - // Decode the RUNNING to a list of waiters, then walk that entire list - // and wake them up. Note that it is crucial that after we store `true` - // in the node it can be free'd! As a result we load the `thread` to - // signal ahead of time and then unpark it after the store. + // Walk the entire linked list of waiters and wake them up (in lifo + // order, last to register is first to wake up). unsafe { + // Right after setting `node.signaled = true` the other thread may + // free `node` if there happens to be has a spurious wakeup. + // So we have to take out the `thread` field and copy the pointer to + // `next` first. let mut queue = (state_and_queue & !STATE_MASK) as *const Waiter; while !queue.is_null() { let next = (*queue).next; - let thread = (*queue).thread.clone(); + let thread = (*queue).thread.replace(None).unwrap(); (*queue).signaled.store(true, Ordering::SeqCst); - thread.unpark(); + // ^- FIXME (maybe): This is another case of issue #55005 + // `store()` has a potentially dangling ref to `signaled`. queue = next; + thread.unpark(); } } } -- cgit 1.4.1-3-g733a5 From c11a44ab6ce693629a03554b8b35d2218bca83cf Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 23 Oct 2019 10:01:22 +0200 Subject: Use more precise atomic orderings --- src/libstd/sync/once.rs | 53 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index ef8a95eed27..4c14fe75643 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -51,6 +51,38 @@ // // You'll find a few more details in the implementation, but that's the gist of // it! +// +// Atomic orderings: +// When running `Once` we deal with multiple atomics: +// `Once.state_and_queue` and an unknown number of `Waiter.signaled`. +// * `state_and_queue` is used (1) as a state flag, (2) for synchronizing the +// result of the `Once`, and (3) for synchronizing `Waiter` nodes. +// - At the end of the `call_inner` function we have to make sure the result +// of the `Once` is acquired. So every load which can be the only one to +// load COMPLETED must have at least Acquire ordering, which means all +// three of them. +// - `WaiterQueue::Drop` is the only place that may store COMPLETED, and +// must do so with Release ordering to make the result available. +// - `wait` inserts `Waiter` nodes as a pointer in `state_and_queue`, and +// needs to make the nodes available with Release ordering. The load in +// its `compare_and_swap` can be Relaxed because it only has to compare +// the atomic, not to read other data. +// - `WaiterQueue::Drop` must see the `Waiter` nodes, so it must load +// `state_and_queue` with Acquire ordering. +// - There is just one store where `state_and_queue` is used only as a +// state flag, without having to synchronize data: switching the state +// from INCOMPLETE to RUNNING in `call_inner`. This store can be Relaxed, +// but the read has to be Acquire because of the requirements mentioned +// above. +// * `Waiter.signaled` is both used as a flag, and to protect a field with +// interior mutability in `Waiter`. `Waiter.thread` is changed in +// `WaiterQueue::Drop` which then sets `signaled` with Release ordering. +// After `wait` loads `signaled` with Acquire and sees it is true, it needs to +// see the changes to drop the `Waiter` struct correctly. +// * There is one place where the two atomics `Once.state_and_queue` and +// `Waiter.signaled` come together, and might be reordered by the compiler or +// processor. Because both use Aquire ordering such a reordering is not +// allowed, so no need for SeqCst. use crate::cell::Cell; use crate::fmt; @@ -337,7 +369,7 @@ impl Once { // An `Acquire` load is enough because that makes all the initialization // operations visible to us, and, this being a fast path, weaker // ordering helps with performance. This `Acquire` synchronizes with - // `SeqCst` operations on the slow path. + // `Release` operations on the slow path. self.state_and_queue.load(Ordering::Acquire) == COMPLETE } @@ -355,12 +387,9 @@ impl Once { #[cold] fn call_inner(&self, ignore_poisoning: bool, - init: &mut dyn FnMut(bool)) { - - // This cold path uses SeqCst consistently because the - // performance difference really does not matter there, and - // SeqCst minimizes the chances of something going wrong. - let mut state_and_queue = self.state_and_queue.load(Ordering::SeqCst); + init: &mut dyn FnMut(bool)) + { + let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire); loop { match state_and_queue { COMPLETE => break, @@ -373,7 +402,7 @@ impl Once { // Try to register this thread as the one RUNNING. let old = self.state_and_queue.compare_and_swap(state_and_queue, RUNNING, - Ordering::SeqCst); + Ordering::Acquire); if old != state_and_queue { state_and_queue = old; continue @@ -395,7 +424,7 @@ impl Once { // pointer to the waiter queue in the more significant bits. assert!(state_and_queue & STATE_MASK == RUNNING); wait(&self.state_and_queue, state_and_queue); - state_and_queue = self.state_and_queue.load(Ordering::SeqCst); + state_and_queue = self.state_and_queue.load(Ordering::Acquire); } } } @@ -438,7 +467,7 @@ fn wait(state_and_queue: &AtomicUsize, current_state: usize) { // drop our `Waiter` node and leave a hole in the linked list (and a // dangling reference). Guard against spurious wakeups by reparking // ourselves until we are signaled. - while !node.signaled.load(Ordering::SeqCst) { + while !node.signaled.load(Ordering::Acquire) { thread::park(); } } @@ -454,7 +483,7 @@ impl Drop for WaiterQueue<'_> { fn drop(&mut self) { // Swap out our state with however we finished. let state_and_queue = self.state_and_queue.swap(self.set_state_on_drop_to, - Ordering::SeqCst); + Ordering::AcqRel); // We should only ever see an old state which was RUNNING. assert_eq!(state_and_queue & STATE_MASK, RUNNING); @@ -470,7 +499,7 @@ impl Drop for WaiterQueue<'_> { while !queue.is_null() { let next = (*queue).next; let thread = (*queue).thread.replace(None).unwrap(); - (*queue).signaled.store(true, Ordering::SeqCst); + (*queue).signaled.store(true, Ordering::Release); // ^- FIXME (maybe): This is another case of issue #55005 // `store()` has a potentially dangling ref to `signaled`. queue = next; -- cgit 1.4.1-3-g733a5 From c2bbfeadcce08a4b8ce02b66906ecc542cc9df39 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Thu, 24 Oct 2019 17:08:23 +0200 Subject: Always align Waiter to 4 bytes --- src/libstd/sync/once.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 4c14fe75643..c135471e2f2 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -171,6 +171,7 @@ const STATE_MASK: usize = 0x3; // `wait` would both hand out a mutable reference to its `Waiter` node, and keep // a shared reference to check `signaled`. Instead we hold shared references and // use interior mutability. +#[repr(align(4))] // Ensure the two lower bits are free to use as state bits. struct Waiter { thread: Cell>, signaled: AtomicBool, -- cgit 1.4.1-3-g733a5 From 3712bb68c4f76161b54dcade7c1497b3ffc32e11 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Fri, 25 Oct 2019 10:01:27 +0200 Subject: Mention park guarantee --- src/libstd/sync/once.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index c135471e2f2..bdb941cff52 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -469,6 +469,10 @@ fn wait(state_and_queue: &AtomicUsize, current_state: usize) { // dangling reference). Guard against spurious wakeups by reparking // ourselves until we are signaled. while !node.signaled.load(Ordering::Acquire) { + // If the managing thread happens to signal and unpark us before we can + // park ourselves, the result could be this thread never gets unparked. + // Luckily `park` comes with the guarantee that if it got an `unpark` + // just before on an unparked thread is does not park. thread::park(); } } -- cgit 1.4.1-3-g733a5 From 900c13e7f465e53a3bae7ff91a1090d6faf29416 Mon Sep 17 00:00:00 2001 From: Marco Conte Date: Fri, 18 Oct 2019 12:28:04 +0100 Subject: enhance the documentation of std::io::BufReader regarding potential data loss --- src/libstd/io/buffered.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 9593a1bae0a..7870c56b476 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -24,7 +24,8 @@ use crate::memchr; /// /// When the `BufReader` is dropped, the contents of its buffer will be /// discarded. Creating multiple instances of a `BufReader` on the same -/// stream can cause data loss. +/// stream can cause data loss, as well as reading from the underlying reader +/// after unwrapping the `BufReader` instance with `BufReader::into_inner()`. /// /// [`Read`]: ../../std/io/trait.Read.html /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read @@ -179,7 +180,8 @@ impl BufReader { /// Unwraps this `BufReader`, returning the underlying reader. /// - /// Note that any leftover data in the internal buffer is lost. + /// Note that any leftover data in the internal buffer is lost. Therefore, + /// a following read from the underlying reader may lead to data loss. /// /// # Examples /// -- cgit 1.4.1-3-g733a5 From 5b5196ad65db877c2f140dfc7a25f3fc6f2e40c6 Mon Sep 17 00:00:00 2001 From: Marco Conte Date: Wed, 23 Oct 2019 18:11:41 +0100 Subject: rephrase sentence regarding data loss when using BufReader::into_inner --- src/libstd/io/buffered.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 7870c56b476..ad567c97c2c 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -24,8 +24,9 @@ use crate::memchr; /// /// When the `BufReader` is dropped, the contents of its buffer will be /// discarded. Creating multiple instances of a `BufReader` on the same -/// stream can cause data loss, as well as reading from the underlying reader -/// after unwrapping the `BufReader` instance with `BufReader::into_inner()`. +/// stream can cause data loss. Reading from the underlying reader after +/// unwrapping the `BufReader` with `BufReader::into_inner` can also cause +/// data loss. /// /// [`Read`]: ../../std/io/trait.Read.html /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read -- cgit 1.4.1-3-g733a5 From 6eddf5cb5eb022c44a6a0541017bbb09b1dd7b73 Mon Sep 17 00:00:00 2001 From: mjptree Date: Sat, 2 Nov 2019 18:30:10 +0000 Subject: Correct error in documentation for Ipv4Addr method Correct statement in doctests on line 539 of `is_global` method of the `Ipv4Addr` object, which falsely attributed the tests to the broadcast address. --- src/libstd/net/ip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 70b68d13485..16176213d1e 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -536,7 +536,7 @@ impl Ipv4Addr { /// // the broadcast address is not global /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); /// - /// // the broadcast address is not global + /// // the address space designated for documentation is not global /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); -- cgit 1.4.1-3-g733a5 From 6f79b71a6979de016c8db3f76fbd6d5cbba39cdc Mon Sep 17 00:00:00 2001 From: mjptree Date: Sun, 3 Nov 2019 16:16:14 +0000 Subject: Correct deprecated `is_global` IPv6 documentation This method does currently not return false for the `site_local` unicast address space. The documentation of the `is_unicast_global` method on lines 1352 - 1382 suggests that this is intentional as the site-local prefix must no longer be supported in new implementations, thus the documentation can safely be updated to reflect that information. If not so, either the `is_unicast_global` method should be updated to exclude the unicast site-local address space, or the `is_global` method itself. --- src/libstd/net/ip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 70b68d13485..719df4449a4 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1130,7 +1130,7 @@ impl Ipv6Addr { /// The following return [`false`]: /// /// - the loopback address - /// - link-local, site-local, and unique local unicast addresses + /// - link-local, and unique local unicast addresses /// - interface-, link-, realm-, admin- and site-local multicast addresses /// /// [`true`]: ../../std/primitive.bool.html -- cgit 1.4.1-3-g733a5 From 5083adeaad7af01b4cbc9244f75690950f7a0c92 Mon Sep 17 00:00:00 2001 From: Umesh Kalappa Date: Wed, 30 Oct 2019 01:38:32 -0700 Subject: Implemented the home_dir for VxWorks --- src/libstd/sys/vxworks/os.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs index f4798da1876..baa6c425d2e 100644 --- a/src/libstd/sys/vxworks/os.rs +++ b/src/libstd/sys/vxworks/os.rs @@ -287,7 +287,8 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - None + crate::env::var_os("HOME").or_else(|| None + ).map(PathBuf::from) } pub fn exit(code: i32) -> ! { -- cgit 1.4.1-3-g733a5 From 23d221153f3d453166a765010f0029369e77b508 Mon Sep 17 00:00:00 2001 From: nia Date: Mon, 4 Nov 2019 17:16:11 +0000 Subject: Use KERN_ARND syscall for random numbers on NetBSD, same as FreeBSD. This system call is present on all supported NetBSD versions and provides an endless stream of non-blocking random data from the kernel's ChaCha20-based CSPRNG. It doesn't require a file descriptor to be opened. The system call is documented here (under kern.arandom): https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-7.0 And defined here: https://nxr.netbsd.org/xref/src/sys/sys/sysctl.h#273 The semantics are the same as FreeBSD so reading 256 bytes per call is fine. Similar change for getrandom crate: rust-random/getrandom#115 --- src/libstd/sys/unix/rand.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index be112f6fc03..decb705a049 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -15,6 +15,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { not(target_os = "ios"), not(target_os = "openbsd"), not(target_os = "freebsd"), + not(target_os = "netbsd"), not(target_os = "fuchsia"), not(target_os = "redox")))] mod imp { @@ -142,7 +143,7 @@ mod imp { } } -#[cfg(target_os = "freebsd")] +#[cfg(target_os = "freebsd", target_os = "netbsd")] mod imp { use crate::ptr; -- cgit 1.4.1-3-g733a5 From b4f92eaea23bee1b8574128878f909b8534b0f3d Mon Sep 17 00:00:00 2001 From: nia Date: Mon, 4 Nov 2019 17:34:29 +0000 Subject: Use any() in code shared between FreeBSD and NetBSD --- src/libstd/sys/unix/rand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index decb705a049..bc387544c4c 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -143,7 +143,7 @@ mod imp { } } -#[cfg(target_os = "freebsd", target_os = "netbsd")] +#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] mod imp { use crate::ptr; -- cgit 1.4.1-3-g733a5 From 4c66658f2c51df8d7d97c975395cc161b8df2f98 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 4 Nov 2019 20:49:47 +0100 Subject: Don't mutate node.next --- src/libstd/sync/once.rs | 70 ++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index bdb941cff52..252a2d4319f 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -87,7 +87,6 @@ use crate::cell::Cell; use crate::fmt; use crate::marker; -use crate::ptr; use crate::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; use crate::thread::{self, Thread}; @@ -432,48 +431,47 @@ impl Once { } } -fn wait(state_and_queue: &AtomicUsize, current_state: usize) { - // Create the node for our current thread that we are going to try to slot - // in at the head of the linked list. - let mut node = Waiter { - thread: Cell::new(Some(thread::current())), - signaled: AtomicBool::new(false), - next: ptr::null(), - }; - let me = &node as *const Waiter as usize; - assert!(me & STATE_MASK == 0); // We assume pointers have 2 free bits that - // we can use for state. - - // Try to slide in the node at the head of the linked list. - // Run in a loop where we make sure the status is still RUNNING, and that - // another thread did not just replace the head of the linked list. - let mut old_head_and_status = current_state; +fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) { + // Note: the following code was carefully written to avoid creating a + // mutable reference to `node` that gets aliased. loop { - if old_head_and_status & STATE_MASK != RUNNING { - return; // No need anymore to enqueue ourselves. + // Don't queue this thread if the status is no longer running, + // otherwise we will not be woken up. + if current_state & STATE_MASK != RUNNING { + return; } - node.next = (old_head_and_status & !STATE_MASK) as *const Waiter; - let old = state_and_queue.compare_and_swap(old_head_and_status, + // Create the node for our current thread. + let node = Waiter { + thread: Cell::new(Some(thread::current())), + signaled: AtomicBool::new(false), + next: (current_state & !STATE_MASK) as *const Waiter, + }; + let me = &node as *const Waiter as usize; + + // Try to slide in the node at the head of the linked list, making sure + // that another thread didn't just replace the head of the linked list. + let old = state_and_queue.compare_and_swap(current_state, me | RUNNING, Ordering::Release); - if old == old_head_and_status { - break; // Success! + if old != current_state { + current_state = old; + continue; } - old_head_and_status = old; - } - // We have enqueued ourselves, now lets wait. - // It is important not to return before being signaled, otherwise we would - // drop our `Waiter` node and leave a hole in the linked list (and a - // dangling reference). Guard against spurious wakeups by reparking - // ourselves until we are signaled. - while !node.signaled.load(Ordering::Acquire) { - // If the managing thread happens to signal and unpark us before we can - // park ourselves, the result could be this thread never gets unparked. - // Luckily `park` comes with the guarantee that if it got an `unpark` - // just before on an unparked thread is does not park. - thread::park(); + // We have enqueued ourselves, now lets wait. + // It is important not to return before being signaled, otherwise we + // would drop our `Waiter` node and leave a hole in the linked list + // (and a dangling reference). Guard against spurious wakeups by + // reparking ourselves until we are signaled. + while !node.signaled.load(Ordering::Acquire) { + // If the managing thread happens to signal and unpark us before we + // can park ourselves, the result could be this thread never gets + // unparked. Luckily `park` comes with the guarantee that if it got + // an `unpark` just before on an unparked thread is does not park. + thread::park(); + } + break; } } -- cgit 1.4.1-3-g733a5 From 002c1c74d99295e49e30a02fb98f25383f1576f8 Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Tue, 5 Nov 2019 19:16:09 +0900 Subject: Improve std::thread::Result documentation --- src/libstd/thread/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 0ffa6ace2e4..2af0a4804ef 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1271,6 +1271,18 @@ impl fmt::Debug for Thread { /// /// Indicates the manner in which a thread exited. /// +/// The value contained in the `Result::Err` variant +/// is the value the thread panicked with; +/// that is, the parameter the `panic!` macro was called with. +/// Unlike with normal errors, this value doesn't implement +/// the `std::error::Error` trait. +/// +/// Thus, a sensible way to handle a thread panic is to either +/// `unwrap` the `Result`, propagating the panic, +/// or in case the thread is intended to be a subsystem boundary +/// that is supposed to isolate system-level failures, +/// match for the `Err` variant and handle the panic in an appropriate way. +/// /// A thread that completes without panicking is considered to exit successfully. /// /// # Examples -- cgit 1.4.1-3-g733a5 From 49e240346fe75eb5380469fb8e901f007fa829c1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 5 Nov 2019 13:17:05 +0000 Subject: libstd: allow `improper_ctypes` in `sys/sgx` Signed-off-by: David Wood --- src/libstd/sys/sgx/abi/mod.rs | 1 + src/libstd/sys/sgx/rwlock.rs | 3 +++ 2 files changed, 4 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs index 0f107de83f0..3a9b1fc8684 100644 --- a/src/libstd/sys/sgx/abi/mod.rs +++ b/src/libstd/sys/sgx/abi/mod.rs @@ -53,6 +53,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) { // (main function exists). If this is a library, the crate author should be // able to specify this #[cfg(not(test))] +#[allow(improper_ctypes)] #[no_mangle] extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) { // FIXME: how to support TLS in library mode? diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index e2f94b1d928..c32e6dd3786 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -172,6 +172,7 @@ const EINVAL: i32 = 22; #[cfg(not(test))] #[no_mangle] +#[allow(improper_ctypes)] pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { if p.is_null() { return EINVAL; @@ -181,6 +182,7 @@ pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { } #[cfg(not(test))] +#[allow(improper_ctypes)] #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { if p.is_null() { @@ -190,6 +192,7 @@ pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { return 0; } #[cfg(not(test))] +#[allow(improper_ctypes)] #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { if p.is_null() { -- cgit 1.4.1-3-g733a5 From f1bc4ef170dc27f7c186e6b00de30f66eee14f6c Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Wed, 6 Nov 2019 14:47:52 +0900 Subject: Addressed review comments. --- src/libstd/thread/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 2af0a4804ef..5a936da05fd 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1273,15 +1273,15 @@ impl fmt::Debug for Thread { /// /// The value contained in the `Result::Err` variant /// is the value the thread panicked with; -/// that is, the parameter the `panic!` macro was called with. +/// that is, the argument the `panic!` macro was called with. /// Unlike with normal errors, this value doesn't implement -/// the `std::error::Error` trait. +/// the [`Error`] trait. /// -/// Thus, a sensible way to handle a thread panic is to either -/// `unwrap` the `Result`, propagating the panic, -/// or in case the thread is intended to be a subsystem boundary +/// Thus, a sensible way to handle a thread panic is to either: +/// 1. `unwrap` the `Result`, propagating the panic +/// 2. or in case the thread is intended to be a subsystem boundary /// that is supposed to isolate system-level failures, -/// match for the `Err` variant and handle the panic in an appropriate way. +/// match on the `Err` variant and handle the panic in an appropriate way. /// /// A thread that completes without panicking is considered to exit successfully. /// -- cgit 1.4.1-3-g733a5 From 1c7595fd0f509637e8da61e3bac425e4f3fd69fa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 25 Oct 2019 07:19:07 +0200 Subject: gate rustc_on_unimplemented under rustc_attrs --- .../src/language-features/on-unimplemented.md | 154 --------------------- src/liballoc/lib.rs | 2 +- src/libcore/lib.rs | 2 +- src/librustc/error_codes.rs | 6 +- src/libstd/lib.rs | 2 +- src/libsyntax/feature_gate/active.rs | 3 - src/libsyntax/feature_gate/builtin_attrs.rs | 15 +- src/libsyntax/feature_gate/removed.rs | 3 + .../issue-59523-on-implemented-is-not-unused.rs | 2 +- .../feature-gates/feature-gate-on-unimplemented.rs | 9 -- .../feature-gate-on-unimplemented.stderr | 12 -- src/test/ui/on-unimplemented/bad-annotation.rs | 2 +- .../on-unimplemented/expected-comma-found-token.rs | 2 +- .../feature-gate-on-unimplemented.rs | 8 ++ .../feature-gate-on-unimplemented.stderr | 12 ++ src/test/ui/on-unimplemented/multiple-impls.rs | 2 +- src/test/ui/on-unimplemented/on-impl.rs | 2 +- src/test/ui/on-unimplemented/on-trait.rs | 2 +- 18 files changed, 42 insertions(+), 198 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/on-unimplemented.md delete mode 100644 src/test/ui/feature-gates/feature-gate-on-unimplemented.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr create mode 100644 src/test/ui/on-unimplemented/feature-gate-on-unimplemented.rs create mode 100644 src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr (limited to 'src/libstd') diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md deleted file mode 100644 index 8db241e4b4e..00000000000 --- a/src/doc/unstable-book/src/language-features/on-unimplemented.md +++ /dev/null @@ -1,154 +0,0 @@ -# `on_unimplemented` - -The tracking issue for this feature is: [#29628] - -[#29628]: https://github.com/rust-lang/rust/issues/29628 - ------------------------- - -The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]` -attribute, which allows trait definitions to add specialized notes to error -messages when an implementation was expected but not found. You can refer -to the trait's generic arguments by name and to the resolved type using -`Self`. - -For example: - -```rust,compile_fail -#![feature(on_unimplemented)] - -#[rustc_on_unimplemented="an iterator over elements of type `{A}` \ - cannot be built from a collection of type `{Self}`"] -trait MyIterator { - fn next(&mut self) -> A; -} - -fn iterate_chars>(i: I) { - // ... -} - -fn main() { - iterate_chars(&[1, 2, 3][..]); -} -``` - -When the user compiles this, they will see the following; - -```txt -error[E0277]: the trait bound `&[{integer}]: MyIterator` is not satisfied - --> :14:5 - | -14 | iterate_chars(&[1, 2, 3][..]); - | ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]` - | - = help: the trait `MyIterator` is not implemented for `&[{integer}]` - = note: required by `iterate_chars` -``` - -`on_unimplemented` also supports advanced filtering for better targeting -of messages, as well as modifying specific parts of the error message. You -target the text of: - - - the main error message (`message`) - - the label (`label`) - - an extra note (`note`) - -For example, the following attribute - -```rust,compile_fail -#[rustc_on_unimplemented( - message="message", - label="label", - note="note" -)] -trait MyIterator { - fn next(&mut self) -> A; -} -``` - -Would generate the following output: - -```text -error[E0277]: message - --> :14:5 - | -14 | iterate_chars(&[1, 2, 3][..]); - | ^^^^^^^^^^^^^ label - | - = note: note - = help: the trait `MyIterator` is not implemented for `&[{integer}]` - = note: required by `iterate_chars` -``` - -To allow more targeted error messages, it is possible to filter the -application of these fields based on a variety of attributes when using -`on`: - - - `crate_local`: whether the code causing the trait bound to not be - fulfilled is part of the user's crate. This is used to avoid suggesting - code changes that would require modifying a dependency. - - Any of the generic arguments that can be substituted in the text can be - referred by name as well for filtering, like `Rhs="i32"`, except for - `Self`. - - `_Self`: to filter only on a particular calculated trait resolution, like - `Self="std::iter::Iterator"`. This is needed because `Self` is a - keyword which cannot appear in attributes. - - `direct`: user-specified rather than derived obligation. - - `from_method`: usable both as boolean (whether the flag is present, like - `crate_local`) or matching against a particular method. Currently used - for `try`. - - `from_desugaring`: usable both as boolean (whether the flag is present) - or matching against a particular desugaring. The desugaring is identified - with its variant name in the `DesugaringKind` enum. - -For example, the `Iterator` trait can be annotated in the following way: - -```rust,compile_fail -#[rustc_on_unimplemented( - on( - _Self="&str", - note="call `.chars()` or `.as_bytes()` on `{Self}" - ), - message="`{Self}` is not an iterator", - label="`{Self}` is not an iterator", - note="maybe try calling `.iter()` or a similar method" -)] -pub trait Iterator {} -``` - -Which would produce the following outputs: - -```text -error[E0277]: `Foo` is not an iterator - --> src/main.rs:4:16 - | -4 | for foo in Foo {} - | ^^^ `Foo` is not an iterator - | - = note: maybe try calling `.iter()` or a similar method - = help: the trait `std::iter::Iterator` is not implemented for `Foo` - = note: required by `std::iter::IntoIterator::into_iter` - -error[E0277]: `&str` is not an iterator - --> src/main.rs:5:16 - | -5 | for foo in "" {} - | ^^ `&str` is not an iterator - | - = note: call `.chars()` or `.bytes() on `&str` - = help: the trait `std::iter::Iterator` is not implemented for `&str` - = note: required by `std::iter::IntoIterator::into_iter` -``` - -If you need to filter on multiple attributes, you can use `all`, `any` or -`not` in the following way: - -```rust,compile_fail -#[rustc_on_unimplemented( - on( - all(_Self="&str", T="std::string::String"), - note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" - ) -)] -pub trait From: Sized { /* ... */ } -``` diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 94379afc2bd..ddfa6797a57 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -116,7 +116,7 @@ #![feature(unsize)] #![feature(unsized_locals)] #![feature(allocator_internals)] -#![feature(on_unimplemented)] +#![cfg_attr(bootstrap, feature(on_unimplemented))] #![feature(rustc_const_unstable)] #![feature(slice_partition_dedup)] #![feature(maybe_uninit_extra, maybe_uninit_slice)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1b67b05c730..ca431627147 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -89,7 +89,7 @@ #![feature(nll)] #![feature(exhaustive_patterns)] #![feature(no_core)] -#![feature(on_unimplemented)] +#![cfg_attr(bootstrap, feature(on_unimplemented))] #![feature(optin_builtin_traits)] #![feature(prelude_import)] #![feature(repr_simd, platform_intrinsics)] diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index f5ff92e69bc..18d98efebd4 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -607,7 +607,7 @@ position that needs that trait. For example, when the following code is compiled: ```compile_fail -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] fn foo>(x: T){} @@ -639,7 +639,7 @@ position that needs that trait. For example, when the following code is compiled: ```compile_fail -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] fn foo>(x: T){} @@ -669,7 +669,7 @@ position that needs that trait. For example, when the following code is compiled: ```compile_fail -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] fn foo>(x: T){} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c7adad896a5..927fd2a6b0b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -284,7 +284,7 @@ #![feature(never_type)] #![feature(nll)] #![cfg_attr(bootstrap, feature(non_exhaustive))] -#![feature(on_unimplemented)] +#![cfg_attr(bootstrap, feature(on_unimplemented))] #![feature(optin_builtin_traits)] #![feature(panic_info_message)] #![feature(panic_internals)] diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 736a363bbfc..1e77eaaae88 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -134,9 +134,6 @@ declare_features! ( /// Allows using `rustc_*` attributes (RFC 572). (active, rustc_attrs, "1.0.0", Some(29642), None), - /// Allows using `#[on_unimplemented(..)]` on traits. - (active, on_unimplemented, "1.0.0", Some(29628), None), - /// Allows using the `box $expr` syntax. (active, box_syntax, "1.0.0", Some(49733), None), diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index eb811c3e0ff..b32a887c6b2 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -166,7 +166,7 @@ macro_rules! experimental { } const IMPL_DETAIL: &str = "internal implementation detail"; -const INTERAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; +const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); @@ -418,14 +418,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ linkage, Whitelisted, template!(NameValueStr: "external|internal|..."), "the `linkage` attribute is experimental and not portable across platforms", ), - rustc_attr!(rustc_std_internal_symbol, Whitelisted, template!(Word), INTERAL_UNSTABLE), + rustc_attr!(rustc_std_internal_symbol, Whitelisted, template!(Word), INTERNAL_UNSTABLE), // ========================================================================== // Internal attributes, Macro related: // ========================================================================== rustc_attr!(rustc_builtin_macro, Whitelisted, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERAL_UNSTABLE), + rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, Whitelisted, template!(NameValueStr: "transparent|semitransparent|opaque"), @@ -436,17 +436,16 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Diagnostics related: // ========================================================================== - gated!( + rustc_attr!( rustc_on_unimplemented, Whitelisted, template!( List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message" ), - on_unimplemented, - experimental!(rustc_on_unimplemented), + INTERNAL_UNSTABLE ), // Whitelists "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!(rustc_conversion_suggestion, Whitelisted, template!(Word), INTERAL_UNSTABLE), + rustc_attr!(rustc_conversion_suggestion, Whitelisted, template!(Word), INTERNAL_UNSTABLE), // ========================================================================== // Internal attributes, Const related: @@ -454,7 +453,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(rustc_promotable, Whitelisted, template!(Word), IMPL_DETAIL), rustc_attr!(rustc_allow_const_fn_ptr, Whitelisted, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_args_required_const, Whitelisted, template!(List: "N"), INTERAL_UNSTABLE), + rustc_attr!(rustc_args_required_const, Whitelisted, template!(List: "N"), INTERNAL_UNSTABLE), // ========================================================================== // Internal attributes, Layout related: diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs index 2c29e1ebf14..c7b931a6f70 100644 --- a/src/libsyntax/feature_gate/removed.rs +++ b/src/libsyntax/feature_gate/removed.rs @@ -99,6 +99,9 @@ declare_features! ( /// + `__register_diagnostic` /// +`__build_diagnostic_array` (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), + /// Allows using `#[on_unimplemented(..)]` on traits. + /// (Moved to `rustc_attrs`.) + (removed, on_unimplemented, "1.40.0", None, None, None), // ------------------------------------------------------------------------- // feature-group-end: removed features diff --git a/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs index 709e9be663e..fa52ca90b10 100644 --- a/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs +++ b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs @@ -5,7 +5,7 @@ // revisions: cfail1 cfail2 // build-pass (FIXME(62277): could be check-pass?) -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] #![deny(unused_attributes)] #[rustc_on_unimplemented = "invalid"] diff --git a/src/test/ui/feature-gates/feature-gate-on-unimplemented.rs b/src/test/ui/feature-gates/feature-gate-on-unimplemented.rs deleted file mode 100644 index bec1531c533..00000000000 --- a/src/test/ui/feature-gates/feature-gate-on-unimplemented.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Test that `#[rustc_on_unimplemented]` is gated by `on_unimplemented` feature -// gate. - -#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] -//~^ ERROR the `#[rustc_on_unimplemented]` attribute is an experimental feature -trait Foo -{} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr deleted file mode 100644 index 6c230f8cada..00000000000 --- a/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[rustc_on_unimplemented]` attribute is an experimental feature - --> $DIR/feature-gate-on-unimplemented.rs:4:1 - | -LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29628 - = help: add `#![feature(on_unimplemented)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/on-unimplemented/bad-annotation.rs b/src/test/ui/on-unimplemented/bad-annotation.rs index 5357c3bff9a..f05436b8c04 100644 --- a/src/test/ui/on-unimplemented/bad-annotation.rs +++ b/src/test/ui/on-unimplemented/bad-annotation.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.rs b/src/test/ui/on-unimplemented/expected-comma-found-token.rs index d8717f360e9..77c0ea17269 100644 --- a/src/test/ui/on-unimplemented/expected-comma-found-token.rs +++ b/src/test/ui/on-unimplemented/expected-comma-found-token.rs @@ -2,7 +2,7 @@ // access to the variable, whether that mutable access be used // for direct assignment or for taking mutable ref. Issue #6801. -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] #[rustc_on_unimplemented( message="the message" diff --git a/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.rs b/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.rs new file mode 100644 index 00000000000..3cc50e3499a --- /dev/null +++ b/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.rs @@ -0,0 +1,8 @@ +// Test that `#[rustc_on_unimplemented]` is gated by `rustc_attrs` feature gate. + +#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] +//~^ ERROR this is an internal attribute that will never be stable +trait Foo +{} + +fn main() {} diff --git a/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr b/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr new file mode 100644 index 00000000000..ec1eaff52bd --- /dev/null +++ b/src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr @@ -0,0 +1,12 @@ +error[E0658]: this is an internal attribute that will never be stable + --> $DIR/feature-gate-on-unimplemented.rs:3:1 + | +LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs index 0aee98b2090..b74957ebcd4 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.rs +++ b/src/test/ui/on-unimplemented/multiple-impls.rs @@ -1,6 +1,6 @@ // Test if the on_unimplemented message override works -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] struct Foo(T); diff --git a/src/test/ui/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs index 9e4c2f6edd7..ab3e67d01fe 100644 --- a/src/test/ui/on-unimplemented/on-impl.rs +++ b/src/test/ui/on-unimplemented/on-impl.rs @@ -1,6 +1,6 @@ // Test if the on_unimplemented message override works -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] #[rustc_on_unimplemented = "invalid"] diff --git a/src/test/ui/on-unimplemented/on-trait.rs b/src/test/ui/on-unimplemented/on-trait.rs index 109cb5ba969..556813cd479 100644 --- a/src/test/ui/on-unimplemented/on-trait.rs +++ b/src/test/ui/on-unimplemented/on-trait.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength -#![feature(on_unimplemented)] +#![feature(rustc_attrs)] pub mod Bar { #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] -- cgit 1.4.1-3-g733a5 From 4317263a311ad4adc54529b5fdcfe1e18fb651be Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Wed, 6 Nov 2019 16:57:59 +0900 Subject: Fix the Error linking. --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 5a936da05fd..a95ebb00714 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1275,7 +1275,7 @@ impl fmt::Debug for Thread { /// is the value the thread panicked with; /// that is, the argument the `panic!` macro was called with. /// Unlike with normal errors, this value doesn't implement -/// the [`Error`] trait. +/// the [`Error`](std::error::Error) trait. /// /// Thus, a sensible way to handle a thread panic is to either: /// 1. `unwrap` the `Result`, propagating the panic -- cgit 1.4.1-3-g733a5 From 936349c81b59581c7c3a834a6b61eb94168e2807 Mon Sep 17 00:00:00 2001 From: 3442853561 <21147967+3442853561@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:39:48 +0800 Subject: Update local.rs Removed parameters not used in the macro --- src/libstd/thread/local.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index cfaab4e22e9..46453b47fca 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -149,7 +149,7 @@ macro_rules! thread_local { #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] #[allow_internal_unsafe] macro_rules! __thread_local_inner { - (@key $(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => { + (@key $t:ty, $init:expr) => { { #[inline] fn __init() -> $t { $init } @@ -184,7 +184,7 @@ macro_rules! __thread_local_inner { }; ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::__thread_local_inner!(@key $(#[$attr])* $vis $name, $t, $init); + $crate::__thread_local_inner!(@key $t, $init); } } -- cgit 1.4.1-3-g733a5 From 62167c09e5941ca5c07d55f7496ab024287206a0 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 6 Nov 2019 19:20:01 +0530 Subject: using 2.0.log(2.0) in examples does not make it clear which is the base and number. This example makes it clear for programmers who take a glance at the example by following the calculation. It is more intuitive, and eliminates the need for executing the example in the playground. --- src/libstd/f64.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 44d25f1b476..0588373dcdc 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -409,10 +409,10 @@ impl f64 { /// # Examples /// /// ``` - /// let five = 5.0_f64; + /// let twenty_five = 25.0_f64; /// - /// // log5(5) - 1 == 0 - /// let abs_difference = (five.log(5.0) - 1.0).abs(); + /// // log5(25) - 2 == 0 + /// let abs_difference = (twenty_five.log(5.0) - 2.0).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -425,10 +425,10 @@ impl f64 { /// # Examples /// /// ``` - /// let two = 2.0_f64; + /// let four = 4.0_f64; /// - /// // log2(2) - 1 == 0 - /// let abs_difference = (two.log2() - 1.0).abs(); + /// // log2(4) - 2 == 0 + /// let abs_difference = (four.log2() - 2.0).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -448,10 +448,10 @@ impl f64 { /// # Examples /// /// ``` - /// let ten = 10.0_f64; + /// let hundred = 100.0_f64; /// - /// // log10(10) - 1 == 0 - /// let abs_difference = (ten.log10() - 1.0).abs(); + /// // log10(100) - 2 == 0 + /// let abs_difference = (hundred.log10() - 2.0).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` -- cgit 1.4.1-3-g733a5 From 8568204f4e934ff93817f948b13a9c804277a6bf Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Thu, 7 Nov 2019 01:45:30 +0900 Subject: Try with crate::error::Error --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index a95ebb00714..0c632d2afbd 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1275,7 +1275,7 @@ impl fmt::Debug for Thread { /// is the value the thread panicked with; /// that is, the argument the `panic!` macro was called with. /// Unlike with normal errors, this value doesn't implement -/// the [`Error`](std::error::Error) trait. +/// the [`Error`](crate::error::Error) trait. /// /// Thus, a sensible way to handle a thread panic is to either: /// 1. `unwrap` the `Result`, propagating the panic -- cgit 1.4.1-3-g733a5 From c965432e1813efea0ae85ba5b5ea523a4df484a9 Mon Sep 17 00:00:00 2001 From: Umesh Kalappa Date: Wed, 30 Oct 2019 02:29:16 -0700 Subject: Ignore these tests ,since the called commands doesn't exist in VxWorks --- src/libstd/process.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 4b0cf8312f1..b1274a08cbe 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1661,7 +1661,7 @@ mod tests { // FIXME(#10380) these tests should not all be ignored on android. #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn smoke() { let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).spawn() @@ -1683,7 +1683,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn exit_reported_right() { let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn() @@ -1698,7 +1698,7 @@ mod tests { #[test] #[cfg(unix)] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn signal_reported_right() { use crate::os::unix::process::ExitStatusExt; @@ -1726,7 +1726,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn stdout_works() { if cfg!(target_os = "windows") { let mut cmd = Command::new("cmd"); @@ -1740,7 +1740,7 @@ mod tests { } #[test] - #[cfg_attr(any(windows, target_os = "android"), ignore)] + #[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] fn set_current_dir_works() { let mut cmd = Command::new("/bin/sh"); cmd.arg("-c").arg("pwd") @@ -1750,7 +1750,7 @@ mod tests { } #[test] - #[cfg_attr(any(windows, target_os = "android"), ignore)] + #[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] fn stdin_works() { let mut p = Command::new("/bin/sh") .arg("-c").arg("read line; echo $line") @@ -1766,7 +1766,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn test_process_status() { let mut status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap() @@ -1792,7 +1792,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn test_process_output_output() { let Output {status, stdout, stderr} = if cfg!(target_os = "windows") { @@ -1808,7 +1808,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn test_process_output_error() { let Output {status, stdout, stderr} = if cfg!(target_os = "windows") { @@ -1823,7 +1823,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn test_finish_once() { let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() @@ -1834,7 +1834,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn test_finish_twice() { let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() @@ -1846,7 +1846,7 @@ mod tests { } #[test] - #[cfg_attr(target_os = "android", ignore)] + #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] fn test_wait_with_output_once() { let prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap() @@ -1881,6 +1881,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "vxworks", ignore)] fn test_override_env() { use crate::env; @@ -1901,6 +1902,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "vxworks", ignore)] fn test_add_to_env() { let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap(); let output = String::from_utf8_lossy(&result.stdout).to_string(); @@ -1910,6 +1912,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "vxworks", ignore)] fn test_capture_env_at_spawn() { use crate::env; @@ -1965,6 +1968,7 @@ mod tests { // Regression tests for #30862. #[test] + #[cfg_attr(target_os = "vxworks", ignore)] fn test_interior_nul_in_env_key_is_error() { match env_cmd().env("has-some-\0\0s-inside", "value").spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), @@ -1973,6 +1977,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "vxworks", ignore)] fn test_interior_nul_in_env_value_is_error() { match env_cmd().env("key", "has-some-\0\0s-inside").spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), -- cgit 1.4.1-3-g733a5 From b05e200867ce633848d34d8a184bf45c7fa905a4 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Sat, 9 Nov 2019 12:46:17 +0100 Subject: Run rustfmt on libstd/sync/once.rs --- src/libstd/sync/once.rs | 61 +++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 252a2d4319f..e8e395247f9 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -87,7 +87,7 @@ use crate::cell::Cell; use crate::fmt; use crate::marker; -use crate::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; +use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use crate::thread::{self, Thread}; /// A synchronization primitive which can be used to run a one-time global @@ -149,7 +149,7 @@ pub struct OnceState { #[rustc_deprecated( since = "1.38.0", reason = "the `new` function is now preferred", - suggestion = "Once::new()", + suggestion = "Once::new()" )] pub const ONCE_INIT: Once = Once::new(); @@ -185,15 +185,11 @@ struct WaiterQueue<'a> { set_state_on_drop_to: usize, } - impl Once { /// Creates a new `Once` value. #[stable(feature = "once_new", since = "1.2.0")] pub const fn new() -> Once { - Once { - state_and_queue: AtomicUsize::new(INCOMPLETE), - _marker: marker::PhantomData, - } + Once { state_and_queue: AtomicUsize::new(INCOMPLETE), _marker: marker::PhantomData } } /// Performs an initialization routine once and only once. The given closure @@ -254,7 +250,10 @@ impl Once { /// /// [poison]: struct.Mutex.html#poisoning #[stable(feature = "rust1", since = "1.0.0")] - pub fn call_once(&self, f: F) where F: FnOnce() { + pub fn call_once(&self, f: F) + where + F: FnOnce(), + { // Fast path check if self.is_completed() { return; @@ -311,16 +310,17 @@ impl Once { /// INIT.call_once(|| {}); /// ``` #[unstable(feature = "once_poison", issue = "33577")] - pub fn call_once_force(&self, f: F) where F: FnOnce(&OnceState) { + pub fn call_once_force(&self, f: F) + where + F: FnOnce(&OnceState), + { // Fast path check if self.is_completed() { return; } let mut f = Some(f); - self.call_inner(true, &mut |p| { - f.take().unwrap()(&OnceState { poisoned: p }) - }); + self.call_inner(true, &mut |p| f.take().unwrap()(&OnceState { poisoned: p })); } /// Returns `true` if some `call_once` call has completed @@ -385,10 +385,7 @@ impl Once { // currently no way to take an `FnOnce` and call it via virtual dispatch // without some allocation overhead. #[cold] - fn call_inner(&self, - ignore_poisoning: bool, - init: &mut dyn FnMut(bool)) - { + fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(bool)) { let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire); loop { match state_and_queue { @@ -397,15 +394,16 @@ impl Once { // Panic to propagate the poison. panic!("Once instance has previously been poisoned"); } - POISONED | - INCOMPLETE => { + POISONED | INCOMPLETE => { // Try to register this thread as the one RUNNING. - let old = self.state_and_queue.compare_and_swap(state_and_queue, - RUNNING, - Ordering::Acquire); + let old = self.state_and_queue.compare_and_swap( + state_and_queue, + RUNNING, + Ordering::Acquire, + ); if old != state_and_queue { state_and_queue = old; - continue + continue; } // `waiter_queue` will manage other waiting threads, and // wake them up on drop. @@ -417,7 +415,7 @@ impl Once { // poisoned or not. init(state_and_queue == POISONED); waiter_queue.set_state_on_drop_to = COMPLETE; - break + break; } _ => { // All other values must be RUNNING with possibly a @@ -451,9 +449,7 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) { // Try to slide in the node at the head of the linked list, making sure // that another thread didn't just replace the head of the linked list. - let old = state_and_queue.compare_and_swap(current_state, - me | RUNNING, - Ordering::Release); + let old = state_and_queue.compare_and_swap(current_state, me | RUNNING, Ordering::Release); if old != current_state { current_state = old; continue; @@ -485,8 +481,8 @@ impl fmt::Debug for Once { impl Drop for WaiterQueue<'_> { fn drop(&mut self) { // Swap out our state with however we finished. - let state_and_queue = self.state_and_queue.swap(self.set_state_on_drop_to, - Ordering::AcqRel); + let state_and_queue = + self.state_and_queue.swap(self.set_state_on_drop_to, Ordering::AcqRel); // We should only ever see an old state which was RUNNING. assert_eq!(state_and_queue & STATE_MASK, RUNNING); @@ -562,10 +558,10 @@ impl OnceState { #[cfg(all(test, not(target_os = "emscripten")))] mod tests { + use super::Once; use crate::panic; use crate::sync::mpsc::channel; use crate::thread; - use super::Once; #[test] fn smoke_once() { @@ -585,8 +581,10 @@ mod tests { let (tx, rx) = channel(); for _ in 0..10 { let tx = tx.clone(); - thread::spawn(move|| { - for _ in 0..4 { thread::yield_now() } + thread::spawn(move || { + for _ in 0..4 { + thread::yield_now() + } unsafe { O.call_once(|| { assert!(!RUN); @@ -675,6 +673,5 @@ mod tests { assert!(t1.join().is_ok()); assert!(t2.join().is_ok()); - } } -- cgit 1.4.1-3-g733a5 From 15863a60e6426fdf282d47258b582be0cf7e0d1a Mon Sep 17 00:00:00 2001 From: mjptree Date: Sat, 9 Nov 2019 12:27:09 +0000 Subject: Update src/libstd/net/ip.rs I assumed some sort of Oxford-comma case here, bit have to admit English is not my first language. Co-Authored-By: kennytm --- src/libstd/net/ip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 719df4449a4..5a3add3678e 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1130,7 +1130,7 @@ impl Ipv6Addr { /// The following return [`false`]: /// /// - the loopback address - /// - link-local, and unique local unicast addresses + /// - link-local and unique local unicast addresses /// - interface-, link-, realm-, admin- and site-local multicast addresses /// /// [`true`]: ../../std/primitive.bool.html -- cgit 1.4.1-3-g733a5 From 04a237b9e2c327e1ad6339afd2f967bfcad38483 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Sun, 10 Nov 2019 23:47:23 +0000 Subject: Fix HashSet::union performance Consider this example: small_set = 0..2, large_set = 0..1000. To efficiently compute the union of these sets, we should * take all elements of the larger set * for each element of the smaller set check it is not in the larger set This is exactly what this commit does. This particular optimization was implemented a year ago, but the author mistaken `<` and `>`. --- src/libstd/collections/hash/set.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 092fb443468..a038ee80210 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -551,7 +551,7 @@ impl HashSet #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, S> { - if self.len() <= other.len() { + if self.len() >= other.len() { Union { iter: self.iter().chain(other.difference(self)), } -- cgit 1.4.1-3-g733a5