From 9412a898fa4ed5065a363bd40ad9401469ed3d54 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx <christiaan@dirkx.email> Date: Wed, 2 Sep 2020 02:35:14 +0200 Subject: [PATCH 01/34] Stabilize `Poll::is_ready` and `is_pending` as const Insta-stabilize the methods `is_ready` and `is_pending` of `Poll`. Possible because of the recent stabilization of const control flow. Also adds a test for these methods in a const context. --- library/core/src/task/poll.rs | 6 ++++-- src/test/ui/consts/std/poll.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/std/poll.rs diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 9383e7c45fa55..a789e4e2593ee 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -39,15 +39,17 @@ impl<T> Poll<T> { /// Returns `true` if this is `Poll::Ready` #[inline] + #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] #[stable(feature = "futures_api", since = "1.36.0")] - pub fn is_ready(&self) -> bool { + pub const fn is_ready(&self) -> bool { matches!(*self, Poll::Ready(_)) } /// Returns `true` if this is `Poll::Pending` #[inline] + #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] #[stable(feature = "futures_api", since = "1.36.0")] - pub fn is_pending(&self) -> bool { + pub const fn is_pending(&self) -> bool { !self.is_ready() } } diff --git a/src/test/ui/consts/std/poll.rs b/src/test/ui/consts/std/poll.rs new file mode 100644 index 0000000000000..28f2ace6715fe --- /dev/null +++ b/src/test/ui/consts/std/poll.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::task::Poll; + +fn main() { + const POLL : Poll<usize> = Poll::Pending; + + const IS_READY : bool = POLL.is_ready(); + assert!(!IS_READY); + + const IS_PENDING : bool = POLL.is_pending(); + assert!(IS_PENDING); +} From ce1d5ed31aff33bbbb116fffabd6107491c464bc Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx <christiaan@dirkx.email> Date: Fri, 4 Sep 2020 01:04:34 +0200 Subject: [PATCH 02/34] Move const tests for `Poll` to `library\core` Part of #76268 --- library/core/tests/lib.rs | 1 + library/core/tests/task.rs | 14 ++++++++++++++ src/test/ui/consts/std/poll.rs | 13 ------------- 3 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 library/core/tests/task.rs delete mode 100644 src/test/ui/consts/std/poll.rs diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 81e621318e141..2c20259fc5855 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -76,5 +76,6 @@ mod result; mod slice; mod str; mod str_lossy; +mod task; mod time; mod tuple; diff --git a/library/core/tests/task.rs b/library/core/tests/task.rs new file mode 100644 index 0000000000000..d71fef9e5c87d --- /dev/null +++ b/library/core/tests/task.rs @@ -0,0 +1,14 @@ +use core::task::Poll; + +#[test] +fn poll_const() { + // test that the methods of `Poll` are usable in a const context + + const POLL: Poll<usize> = Poll::Pending; + + const IS_READY: bool = POLL.is_ready(); + assert!(!IS_READY); + + const IS_PENDING: bool = POLL.is_pending(); + assert!(IS_PENDING); +} diff --git a/src/test/ui/consts/std/poll.rs b/src/test/ui/consts/std/poll.rs deleted file mode 100644 index 28f2ace6715fe..0000000000000 --- a/src/test/ui/consts/std/poll.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass - -use std::task::Poll; - -fn main() { - const POLL : Poll<usize> = Poll::Pending; - - const IS_READY : bool = POLL.is_ready(); - assert!(!IS_READY); - - const IS_PENDING : bool = POLL.is_pending(); - assert!(IS_PENDING); -} From c027844795e427e63ef917ba40c71d0559d88b79 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Tue, 6 Oct 2020 14:06:25 +0100 Subject: [PATCH 03/34] Fill in things needed to stabilize int_error_matching --- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_middle/src/middle/limits.rs | 8 +-- library/core/src/num/error.rs | 33 ++++++------ library/core/src/num/mod.rs | 12 ++--- library/core/tests/lib.rs | 1 - library/core/tests/nonzero.rs | 4 +- library/core/tests/num/mod.rs | 63 +++++++++++++--------- library/std/src/lib.rs | 1 - library/std/src/num.rs | 7 +-- 9 files changed, 66 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index fa885ce2e7cdf..37bc1a305b2f8 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -46,7 +46,6 @@ #![feature(crate_visibility_modifier)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] -#![feature(int_error_matching)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index def9e5ebb527f..6b6df3a303c22 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -48,10 +48,12 @@ fn update_limit( .unwrap_or(attr.span); let error_str = match e.kind() { - IntErrorKind::Overflow => "`limit` is too large", - IntErrorKind::Empty => "`limit` must be a non-negative integer", + IntErrorKind::PosOverflow => "`limit` is too large", + IntErrorKind::Empty | IntErrorKind::OnlySign => { + "`limit` must be a non-negative integer" + } IntErrorKind::InvalidDigit => "not a valid integer", - IntErrorKind::Underflow => bug!("`limit` should never underflow"), + IntErrorKind::NegOverflow => bug!("`limit` should never underflow"), IntErrorKind::Zero => bug!("zero is a valid `limit`"), kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), }; diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index aab1715518611..9705226ba243a 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -77,51 +77,47 @@ pub struct ParseIntError { /// # Example /// /// ``` -/// #![feature(int_error_matching)] -/// /// # fn main() { /// if let Err(e) = i32::from_str_radix("a12", 10) { /// println!("Failed conversion to i32: {:?}", e.kind()); /// } /// # } /// ``` -#[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" -)] +#[stable(feature = "int_error_matching", since = "1.47.0")] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { /// Value being parsed is empty. /// /// Among other causes, this variant will be constructed when parsing an empty string. + #[stable(feature = "int_error_matching", since = "1.47.0")] Empty, /// Contains an invalid digit. /// /// Among other causes, this variant will be constructed when parsing a string that /// contains a letter. + #[stable(feature = "int_error_matching", since = "1.47.0")] InvalidDigit, /// Integer is too large to store in target integer type. - Overflow, + #[stable(feature = "int_error_matching", since = "1.47.0")] + PosOverflow, /// Integer is too small to store in target integer type. - Underflow, + #[stable(feature = "int_error_matching", since = "1.47.0")] + NegOverflow, /// Value was Zero /// /// This variant will be emitted when the parsing string has a value of zero, which /// would be illegal for non-zero types. + #[stable(feature = "int_error_matching", since = "1.47.0")] Zero, + /// The value contains nothing other than signs `+` or `-`. + #[stable(feature = "int_error_matching", since = "1.47.0")] + OnlySign, } impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. - #[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" - )] + #[stable(feature = "int_error_matching", since = "1.47.0")] pub fn kind(&self) -> &IntErrorKind { &self.kind } @@ -136,9 +132,10 @@ impl ParseIntError { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", IntErrorKind::InvalidDigit => "invalid digit found in string", - IntErrorKind::Overflow => "number too large to fit in target type", - IntErrorKind::Underflow => "number too small to fit in target type", + IntErrorKind::PosOverflow => "number too large to fit in target type", + IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", + IntErrorKind::OnlySign => "only signs without digits found in string", } } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 4f64e30ccf84a..67b4b885dd2ec 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -63,7 +63,7 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No #[stable(feature = "try_from", since = "1.34.0")] pub use error::TryFromIntError; -#[unstable(feature = "int_error_matching", issue = "22639")] +#[stable(feature = "int_error_matching", since = "1.47.0")] pub use error::IntErrorKind; macro_rules! usize_isize_to_xe_bytes_doc { @@ -836,7 +836,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par }; if digits.is_empty() { - return Err(PIE { kind: Empty }); + return Err(PIE { kind: OnlySign }); } let mut result = T::from_u32(0); @@ -849,11 +849,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par }; result = match result.checked_mul(radix) { Some(result) => result, - None => return Err(PIE { kind: Overflow }), + None => return Err(PIE { kind: PosOverflow }), }; result = match result.checked_add(x) { Some(result) => result, - None => return Err(PIE { kind: Overflow }), + None => return Err(PIE { kind: PosOverflow }), }; } } else { @@ -865,11 +865,11 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par }; result = match result.checked_mul(radix) { Some(result) => result, - None => return Err(PIE { kind: Underflow }), + None => return Err(PIE { kind: NegOverflow }), }; result = match result.checked_sub(x) { Some(result) => result, - None => return Err(PIE { kind: Underflow }), + None => return Err(PIE { kind: NegOverflow }), }; } } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index d8b36beb3e085..c128691fa7525 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -37,7 +37,6 @@ #![feature(try_trait)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] -#![feature(int_error_matching)] #![feature(array_value_iter)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index 825e5e63b59bc..fb1293c99bba9 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -135,11 +135,11 @@ fn test_from_str() { ); assert_eq!( "-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()), - Some(IntErrorKind::Underflow) + Some(IntErrorKind::NegOverflow) ); assert_eq!( "257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), - Some(IntErrorKind::Overflow) + Some(IntErrorKind::PosOverflow) ); } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 939f1325c8499..d6f92f25e7846 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -2,10 +2,11 @@ use core::cmp::PartialEq; use core::convert::{TryFrom, TryInto}; use core::fmt::Debug; use core::marker::Copy; -use core::num::TryFromIntError; +use core::num::{IntErrorKind, ParseIntError, TryFromIntError}; use core::ops::{Add, Div, Mul, Rem, Sub}; use core::option::Option; -use core::option::Option::{None, Some}; +use core::option::Option::None; +use core::str::FromStr; #[macro_use] mod int_macros; @@ -65,6 +66,14 @@ where assert_eq!(ten.rem(two), ten % two); } +fn test_parse<T>(num_str: &str, expected: Result<T, IntErrorKind>) +where + T: FromStr<Err = ParseIntError>, + Result<T, IntErrorKind>: PartialEq + Debug, +{ + assert_eq!(num_str.parse::<T>().map_err(|e| e.kind().clone()), expected) +} + #[test] fn from_str_issue7588() { let u: Option<u8> = u8::from_str_radix("1000", 10).ok(); @@ -75,49 +84,51 @@ fn from_str_issue7588() { #[test] fn test_int_from_str_overflow() { - assert_eq!("127".parse::<i8>().ok(), Some(127i8)); - assert_eq!("128".parse::<i8>().ok(), None); + test_parse::<i8>("127", Ok(127)); + test_parse::<i8>("128", Err(IntErrorKind::PosOverflow)); - assert_eq!("-128".parse::<i8>().ok(), Some(-128i8)); - assert_eq!("-129".parse::<i8>().ok(), None); + test_parse::<i8>("-128", Ok(-128)); + test_parse::<i8>("-129", Err(IntErrorKind::NegOverflow)); - assert_eq!("32767".parse::<i16>().ok(), Some(32_767i16)); - assert_eq!("32768".parse::<i16>().ok(), None); + test_parse::<i16>("32767", Ok(32_767)); + test_parse::<i16>("32768", Err(IntErrorKind::PosOverflow)); - assert_eq!("-32768".parse::<i16>().ok(), Some(-32_768i16)); - assert_eq!("-32769".parse::<i16>().ok(), None); + test_parse::<i16>("-32768", Ok(-32_768)); + test_parse::<i16>("-32769", Err(IntErrorKind::NegOverflow)); - assert_eq!("2147483647".parse::<i32>().ok(), Some(2_147_483_647i32)); - assert_eq!("2147483648".parse::<i32>().ok(), None); + test_parse::<i32>("2147483647", Ok(2_147_483_647)); + test_parse::<i32>("2147483648", Err(IntErrorKind::PosOverflow)); - assert_eq!("-2147483648".parse::<i32>().ok(), Some(-2_147_483_648i32)); - assert_eq!("-2147483649".parse::<i32>().ok(), None); + test_parse::<i32>("-2147483648", Ok(-2_147_483_648)); + test_parse::<i32>("-2147483649", Err(IntErrorKind::NegOverflow)); - assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(9_223_372_036_854_775_807i64)); - assert_eq!("9223372036854775808".parse::<i64>().ok(), None); + test_parse::<i64>("9223372036854775807", Ok(9_223_372_036_854_775_807)); + test_parse::<i64>("9223372036854775808", Err(IntErrorKind::PosOverflow)); - assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(-9_223_372_036_854_775_808i64)); - assert_eq!("-9223372036854775809".parse::<i64>().ok(), None); + test_parse::<i64>("-9223372036854775808", Ok(-9_223_372_036_854_775_808)); + test_parse::<i64>("-9223372036854775809", Err(IntErrorKind::NegOverflow)); } #[test] fn test_leading_plus() { - assert_eq!("+127".parse::<u8>().ok(), Some(127)); - assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807)); + test_parse::<u8>("+127", Ok(127)); + test_parse::<i64>("+9223372036854775807", Ok(9223372036854775807)); } #[test] fn test_invalid() { - assert_eq!("--129".parse::<i8>().ok(), None); - assert_eq!("++129".parse::<i8>().ok(), None); - assert_eq!("Съешь".parse::<u8>().ok(), None); + test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit)); + // is this the correct error here. Maybe need a reapeat sign error here + test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit)); } #[test] fn test_empty() { - assert_eq!("-".parse::<i8>().ok(), None); - assert_eq!("+".parse::<i8>().ok(), None); - assert_eq!("".parse::<u8>().ok(), None); + test_parse::<i8>("-", Err(IntErrorKind::OnlySign)); + test_parse::<i8>("+", Err(IntErrorKind::OnlySign)); + test_parse::<u8>("", Err(IntErrorKind::Empty)); } #[test] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ac0075ad129c5..fa23229066cf1 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -264,7 +264,6 @@ #![feature(global_asm)] #![feature(hashmap_internals)] #![feature(int_error_internals)] -#![feature(int_error_matching)] #![feature(integer_atomics)] #![feature(into_future)] #![feature(lang_items)] diff --git a/library/std/src/num.rs b/library/std/src/num.rs index 0f1c596268594..ac3b055cdb050 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -22,12 +22,7 @@ pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, #[stable(feature = "nonzero", since = "1.28.0")] pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; -#[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" -)] +#[stable(feature = "int_error_matching", since = "1.47.0")] pub use core::num::IntErrorKind; #[cfg(test)] From 83d294f06a8f78f4956333a5285bb2c4f7b8a6a9 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Tue, 6 Oct 2020 19:05:25 +0100 Subject: [PATCH 04/34] Bring char along with InvalidDigit --- compiler/rustc_middle/src/middle/limits.rs | 2 +- library/core/src/num/error.rs | 6 +++--- library/core/src/num/mod.rs | 4 ++-- library/core/tests/nonzero.rs | 2 +- library/core/tests/num/mod.rs | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index 6b6df3a303c22..f03f439f73b5a 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -52,7 +52,7 @@ fn update_limit( IntErrorKind::Empty | IntErrorKind::OnlySign => { "`limit` must be a non-negative integer" } - IntErrorKind::InvalidDigit => "not a valid integer", + IntErrorKind::InvalidDigit(_) => "not a valid integer", IntErrorKind::NegOverflow => bug!("`limit` should never underflow"), IntErrorKind::Zero => bug!("zero is a valid `limit`"), kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 9705226ba243a..ba7c94656ce3f 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -92,12 +92,12 @@ pub enum IntErrorKind { /// Among other causes, this variant will be constructed when parsing an empty string. #[stable(feature = "int_error_matching", since = "1.47.0")] Empty, - /// Contains an invalid digit. + /// Contains an digit invalid in its context. /// /// Among other causes, this variant will be constructed when parsing a string that /// contains a letter. #[stable(feature = "int_error_matching", since = "1.47.0")] - InvalidDigit, + InvalidDigit(#[stable(feature = "int_error_matching", since = "1.47.0")] char), /// Integer is too large to store in target integer type. #[stable(feature = "int_error_matching", since = "1.47.0")] PosOverflow, @@ -131,7 +131,7 @@ impl ParseIntError { pub fn __description(&self) -> &str { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", - IntErrorKind::InvalidDigit => "invalid digit found in string", + IntErrorKind::InvalidDigit(_) => "invalid digit found in string", IntErrorKind::PosOverflow => "number too large to fit in target type", IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 67b4b885dd2ec..a438f3161a3af 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -845,7 +845,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par for &c in digits { let x = match (c as char).to_digit(radix) { Some(x) => x, - None => return Err(PIE { kind: InvalidDigit }), + None => return Err(PIE { kind: InvalidDigit(c as char) }), }; result = match result.checked_mul(radix) { Some(result) => result, @@ -861,7 +861,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par for &c in digits { let x = match (c as char).to_digit(radix) { Some(x) => x, - None => return Err(PIE { kind: InvalidDigit }), + None => return Err(PIE { kind: InvalidDigit(c as char) }), }; result = match result.checked_mul(radix) { Some(result) => result, diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index fb1293c99bba9..949d4ea32f064 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -131,7 +131,7 @@ fn test_from_str() { assert_eq!("0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), Some(IntErrorKind::Zero)); assert_eq!( "-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), - Some(IntErrorKind::InvalidDigit) + Some(IntErrorKind::InvalidDigit('-')) ); assert_eq!( "-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()), diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index d6f92f25e7846..a93cd38160b58 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -117,11 +117,11 @@ fn test_leading_plus() { #[test] fn test_invalid() { - test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit)); - test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit)); - test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit)); - // is this the correct error here. Maybe need a reapeat sign error here - test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit('-'))); + test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit('+'))); + test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit('Ð'))); + test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit('H'))); + test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit('-'))); } #[test] From 8eaf0de1f45924a0fdbde00d4c7fe0333b377993 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Tue, 6 Oct 2020 21:03:10 +0100 Subject: [PATCH 05/34] Remove incorrect plural --- library/core/src/num/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index ba7c94656ce3f..a8f8a7804fd78 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -110,7 +110,7 @@ pub enum IntErrorKind { /// would be illegal for non-zero types. #[stable(feature = "int_error_matching", since = "1.47.0")] Zero, - /// The value contains nothing other than signs `+` or `-`. + /// The value contains nothing other than sign `+` or `-`. #[stable(feature = "int_error_matching", since = "1.47.0")] OnlySign, } @@ -135,7 +135,7 @@ impl ParseIntError { IntErrorKind::PosOverflow => "number too large to fit in target type", IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", - IntErrorKind::OnlySign => "only signs without digits found in string", + IntErrorKind::OnlySign => "only sign without digits found in string", } } } From 1e7e2e40e4992a82b9e5bc7120bd33964bcef355 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Tue, 6 Oct 2020 22:42:33 +0100 Subject: [PATCH 06/34] remove OnlySign in favour of InvalidDigit --- compiler/rustc_middle/src/middle/limits.rs | 4 +--- library/core/src/num/error.rs | 9 ++++----- library/core/src/num/mod.rs | 7 +++---- library/core/tests/num/mod.rs | 5 +++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index f03f439f73b5a..e0d171fa77125 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -49,9 +49,7 @@ fn update_limit( let error_str = match e.kind() { IntErrorKind::PosOverflow => "`limit` is too large", - IntErrorKind::Empty | IntErrorKind::OnlySign => { - "`limit` must be a non-negative integer" - } + IntErrorKind::Empty => "`limit` must be a non-negative integer", IntErrorKind::InvalidDigit(_) => "not a valid integer", IntErrorKind::NegOverflow => bug!("`limit` should never underflow"), IntErrorKind::Zero => bug!("zero is a valid `limit`"), diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index a8f8a7804fd78..401d52eb08481 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -95,7 +95,10 @@ pub enum IntErrorKind { /// Contains an digit invalid in its context. /// /// Among other causes, this variant will be constructed when parsing a string that - /// contains a letter. + /// contains a non-asci char. + /// + /// This variant is also constructed when a `+` or `-` is misplaced within a sting + /// either on its own or in the middle of a number. #[stable(feature = "int_error_matching", since = "1.47.0")] InvalidDigit(#[stable(feature = "int_error_matching", since = "1.47.0")] char), /// Integer is too large to store in target integer type. @@ -110,9 +113,6 @@ pub enum IntErrorKind { /// would be illegal for non-zero types. #[stable(feature = "int_error_matching", since = "1.47.0")] Zero, - /// The value contains nothing other than sign `+` or `-`. - #[stable(feature = "int_error_matching", since = "1.47.0")] - OnlySign, } impl ParseIntError { @@ -135,7 +135,6 @@ impl ParseIntError { IntErrorKind::PosOverflow => "number too large to fit in target type", IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", - IntErrorKind::OnlySign => "only sign without digits found in string", } } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index a438f3161a3af..fd00a072d896c 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -830,15 +830,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par let src = src.as_bytes(); let (is_positive, digits) = match src[0] { + b'+' | b'-' if src[1..].is_empty() => { + return Err(PIE { kind: InvalidDigit(src[0] as char) }); + } b'+' => (true, &src[1..]), b'-' if is_signed_ty => (false, &src[1..]), _ => (true, src), }; - if digits.is_empty() { - return Err(PIE { kind: OnlySign }); - } - let mut result = T::from_u32(0); if is_positive { // The number is positive diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index a93cd38160b58..4fd9f721b823b 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -122,12 +122,13 @@ fn test_invalid() { test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit('Ð'))); test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit('H'))); test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit('-'))); + test_parse::<i8>("-", Err(IntErrorKind::InvalidDigit('-'))); + test_parse::<i8>("+", Err(IntErrorKind::InvalidDigit('+'))); + test_parse::<u8>("-1", Err(IntErrorKind::InvalidDigit('-'))); } #[test] fn test_empty() { - test_parse::<i8>("-", Err(IntErrorKind::OnlySign)); - test_parse::<i8>("+", Err(IntErrorKind::OnlySign)); test_parse::<u8>("", Err(IntErrorKind::Empty)); } From f233abb9091e3c0999f0cb80ba652d6094e3d5b4 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Wed, 7 Oct 2020 08:02:36 +0100 Subject: [PATCH 07/34] Add comment to helper function --- library/core/tests/num/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 4fd9f721b823b..12e52252278c5 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -66,6 +66,7 @@ where assert_eq!(ten.rem(two), ten % two); } +/// Helper function for asserting number parsing returns a specific error fn test_parse<T>(num_str: &str, expected: Result<T, IntErrorKind>) where T: FromStr<Err = ParseIntError>, From 91a9f83dd1d73cfd451f81306361df3fafad84a5 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Fri, 16 Oct 2020 09:09:20 -0700 Subject: [PATCH 08/34] Define `fs::hard_link` to not follow symlinks. POSIX leaves it implementation-defined whether `link` follows symlinks. In practice, for example, on Linux it does not and on FreeBSD it does. So, switch to `linkat`, so that we can pick a behavior rather than depending on OS defaults. Pick the option to not follow symlinks. This is somewhat arbitrary, but seems the less surprising choice because hard linking is a very low-level feature which requires the source and destination to be on the same mounted filesystem, and following a symbolic link could end up in a different mounted filesystem. --- library/std/src/fs.rs | 7 +++-- library/std/src/fs/tests.rs | 51 ++++++++++++++++++++++++++++++++++ library/std/src/sys/unix/fs.rs | 5 +++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 161bfe3795c2c..c611bf4d74a49 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1701,10 +1701,13 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. /// +/// If `src` names a symbolic link, it is not followed. The created hard link +/// points to the symbolic link itself. +/// /// # Platform-specific behavior /// -/// This function currently corresponds to the `link` function on Unix -/// and the `CreateHardLink` function on Windows. +/// This function currently corresponds to the `linkat` function with no flags +/// on Unix and the `CreateHardLink` function on Windows. /// Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 65a29076fefa8..8a723d3b4ae22 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1337,3 +1337,54 @@ fn metadata_access_times() { } } } + +/// Test creating hard links to symlinks. +#[test] +fn symlink_hard_link() { + let tmpdir = tmpdir(); + + // Create "file", a file. + check!(fs::File::create(tmpdir.join("file"))); + + // Create "symlink", a symlink to "file". + check!(symlink_file("file", tmpdir.join("symlink"))); + + // Create "hard_link", a hard link to "symlink". + check!(fs::hard_link(tmpdir.join("symlink"), tmpdir.join("hard_link"))); + + // "hard_link" should appear as a symlink. + assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); + + // We sould be able to open "file" via any of the above names. + let _ = check!(fs::File::open(tmpdir.join("file"))); + assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); + let _ = check!(fs::File::open(tmpdir.join("symlink"))); + let _ = check!(fs::File::open(tmpdir.join("hard_link"))); + + // Rename "file" to "file.renamed". + check!(fs::rename(tmpdir.join("file"), tmpdir.join("file.renamed"))); + + // Now, the symlink and the hard link should be dangling. + assert!(fs::File::open(tmpdir.join("file")).is_err()); + let _ = check!(fs::File::open(tmpdir.join("file.renamed"))); + assert!(fs::File::open(tmpdir.join("symlink")).is_err()); + assert!(fs::File::open(tmpdir.join("hard_link")).is_err()); + + // The symlink and the hard link should both still point to "file". + assert!(fs::read_link(tmpdir.join("file")).is_err()); + assert!(fs::read_link(tmpdir.join("file.renamed")).is_err()); + assert_eq!(check!(fs::read_link(tmpdir.join("symlink"))), Path::new("file")); + assert_eq!(check!(fs::read_link(tmpdir.join("hard_link"))), Path::new("file")); + + // Remove "file.renamed". + check!(fs::remove_file(tmpdir.join("file.renamed"))); + + // Now, we can't open the file by any name. + assert!(fs::File::open(tmpdir.join("file")).is_err()); + assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); + assert!(fs::File::open(tmpdir.join("symlink")).is_err()); + assert!(fs::File::open(tmpdir.join("hard_link")).is_err()); + + // "hard_link" should still appear as a symlink. + assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); +} diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 819e8ef18415b..88693e4786c0f 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1067,7 +1067,10 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; - cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it + // implmentation-defined whether it follows symlinks. Pass 0 as the + // `linkat` flags argument so that we don't follow symlinks. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; Ok(()) } From 5e80c65102f85700e1a449847dfa603e589df950 Mon Sep 17 00:00:00 2001 From: CDirkx <christiaan@dirkx.email> Date: Fri, 16 Oct 2020 21:29:21 +0200 Subject: [PATCH 09/34] Bump version to 1.49.0 Due to the recent release of 1.47.0, this PR will be stabilized in 1.49.0 instead of 1.48.0. --- library/core/src/task/poll.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index a789e4e2593ee..dc405465f5d36 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -39,7 +39,7 @@ impl<T> Poll<T> { /// Returns `true` if this is `Poll::Ready` #[inline] - #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] + #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] pub const fn is_ready(&self) -> bool { matches!(*self, Poll::Ready(_)) @@ -47,7 +47,7 @@ impl<T> Poll<T> { /// Returns `true` if this is `Poll::Pending` #[inline] - #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] + #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] pub const fn is_pending(&self) -> bool { !self.is_ready() From 23a5c214150f462043ab411f87ef297309421d71 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Mon, 19 Oct 2020 07:21:41 -0700 Subject: [PATCH 10/34] Fix a typo in a comment. --- library/std/src/sys/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 88693e4786c0f..69f6b88a3bc56 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1068,7 +1068,7 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it - // implmentation-defined whether it follows symlinks. Pass 0 as the + // implementation-defined whether it follows symlinks. Pass 0 as the // `linkat` flags argument so that we don't follow symlinks. cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; Ok(()) From ce00b3e2e0c5c0c88fe59fb45a1c25a8ff9e1836 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Mon, 19 Oct 2020 07:47:32 -0700 Subject: [PATCH 11/34] Use `link` on platforms which lack `linkat`. --- library/std/src/sys/unix/fs.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 69f6b88a3bc56..bf4c941928719 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1067,10 +1067,20 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; - // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it - // implementation-defined whether it follows symlinks. Pass 0 as the - // `linkat` flags argument so that we don't follow symlinks. - cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox"))] { + // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX + // leaves it implementation-defined whether `link` follows symlinks, + // so rely on the `symlink_hard_link` test in + // library/std/src/fs/tests.rs to check the behavior. + cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + } else { + // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives + // us a flag to specify how symlinks should be handled. Pass 0 as + // the flags argument, meaning don't follow symlinks. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; + } + } Ok(()) } From 628fb9ff4a36c706789980276c165c4f013780cf Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe <tshepang@gmail.com> Date: Wed, 21 Oct 2020 04:44:59 +0200 Subject: [PATCH 12/34] make concurrency helper more pleasant to read --- library/test/src/helpers/concurrency.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index 7e9bd50f5566e..c39a9b0ec0233 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -1,18 +1,14 @@ //! Helper module which helps to determine amount of threads to be used //! during tests execution. -use std::env; -use std::thread; +use std::{env, num::NonZeroUsize, thread}; -#[allow(deprecated)] pub fn get_concurrency() -> usize { - match env::var("RUST_TEST_THREADS") { - Ok(s) => { - let opt_n: Option<usize> = s.parse().ok(); - match opt_n { - Some(n) if n > 0 => n, - _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", s), - } + if let Ok(value) = env::var("RUST_TEST_THREADS") { + match value.parse::<NonZeroUsize>().ok() { + Some(n) => n.get(), + _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", value), } - Err(..) => thread::available_concurrency().map(|n| n.get()).unwrap_or(1), + } else { + thread::available_concurrency().map(|n| n.get()).unwrap_or(1) } } From d0178b4f99c70d2443f9b76421429d0d23dadc45 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Tue, 20 Oct 2020 16:42:31 -0700 Subject: [PATCH 13/34] Make it platform-specific whether `hard_link` follows symlinks. Also mention that where possible, `hard_link` does not follow symlinks. --- library/std/src/fs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c611bf4d74a49..c256f556b3c8f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1701,8 +1701,9 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. /// -/// If `src` names a symbolic link, it is not followed. The created hard link -/// points to the symbolic link itself. +/// If `src` names a symbolic link, it is platform-specific whether the symbolic +/// link is followed. On platforms where it's possible to not follow it, it is +/// not followed, and the created hard link points to the symbolic link itself. /// /// # Platform-specific behavior /// From 6249cda78f0cd32b60fb11702b7ffef3e3bab0b2 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Fri, 23 Oct 2020 15:39:02 -0700 Subject: [PATCH 14/34] Disable use of `linkat` on Android as well. According to [the bionic status page], `linkat` has only been available since API level 21. Since Android is based on Linux and Linux's `link` doesn't follow symlinks, just use `link` on Android. [the bionic status page]: https://android.googlesource.com/platform/bionic/+/master/docs/status.md --- library/std/src/sys/unix/fs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index bf4c941928719..ec721fccaa622 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1068,11 +1068,11 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox"))] { - // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX - // leaves it implementation-defined whether `link` follows symlinks, - // so rely on the `symlink_hard_link` test in - // library/std/src/fs/tests.rs to check the behavior. + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] { + // VxWorks, Redox, and old versions of Android lack `linkat`, so use + // `link` instead. POSIX leaves it implementation-defined whether + // `link` follows symlinks, so rely on the `symlink_hard_link` test + // in library/std/src/fs/tests.rs to check the behavior. cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; } else { // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives From 199c36115f1daa71458e94db0f37ab213d01eb8a Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Mon, 26 Oct 2020 05:50:28 -0500 Subject: [PATCH 15/34] Fix spelling eror Co-authored-by: Ashley Mannix <kodraus@hey.com> --- library/core/src/num/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 401d52eb08481..91a24e7740ad4 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -97,7 +97,7 @@ pub enum IntErrorKind { /// Among other causes, this variant will be constructed when parsing a string that /// contains a non-asci char. /// - /// This variant is also constructed when a `+` or `-` is misplaced within a sting + /// This variant is also constructed when a `+` or `-` is misplaced within a string /// either on its own or in the middle of a number. #[stable(feature = "int_error_matching", since = "1.47.0")] InvalidDigit(#[stable(feature = "int_error_matching", since = "1.47.0")] char), From 69c301f0f36696f93a90bb7a6afe9081b0d04233 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Mon, 26 Oct 2020 05:51:07 -0500 Subject: [PATCH 16/34] Small reword Co-authored-by: Ashley Mannix <kodraus@hey.com> --- library/core/src/num/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 91a24e7740ad4..d1a65aa35ae25 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -92,7 +92,7 @@ pub enum IntErrorKind { /// Among other causes, this variant will be constructed when parsing an empty string. #[stable(feature = "int_error_matching", since = "1.47.0")] Empty, - /// Contains an digit invalid in its context. + /// Contains an invalid digit in its context. /// /// Among other causes, this variant will be constructed when parsing a string that /// contains a non-asci char. From 75e6deefee8dc68fc35bdfe5effbfdb517b03f9c Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Mon, 26 Oct 2020 05:51:22 -0500 Subject: [PATCH 17/34] asci -> ASCII Co-authored-by: Ashley Mannix <kodraus@hey.com> --- library/core/src/num/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index d1a65aa35ae25..e1684719ab4ec 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -95,7 +95,7 @@ pub enum IntErrorKind { /// Contains an invalid digit in its context. /// /// Among other causes, this variant will be constructed when parsing a string that - /// contains a non-asci char. + /// contains a non-ASCII char. /// /// This variant is also constructed when a `+` or `-` is misplaced within a string /// either on its own or in the middle of a number. From ad2d93da1f051970555a8be0baa8e6277b3a06c1 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Mon, 26 Oct 2020 18:14:12 +0000 Subject: [PATCH 18/34] Apply suggested changes --- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/middle/limits.rs | 6 ++++-- library/core/src/lib.rs | 1 + library/core/src/num/error.rs | 25 ++++++++++++++-------- library/core/src/num/mod.rs | 13 +++++++---- library/core/tests/lib.rs | 1 + library/core/tests/nonzero.rs | 2 +- library/core/tests/num/mod.rs | 16 +++++++------- library/std/src/lib.rs | 1 + library/std/src/num.rs | 7 +++++- 10 files changed, 48 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 37bc1a305b2f8..fa885ce2e7cdf 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -46,6 +46,7 @@ #![feature(crate_visibility_modifier)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] +#![feature(int_error_matching)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index e0d171fa77125..9ff2b7f08fe04 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -50,8 +50,10 @@ fn update_limit( let error_str = match e.kind() { IntErrorKind::PosOverflow => "`limit` is too large", IntErrorKind::Empty => "`limit` must be a non-negative integer", - IntErrorKind::InvalidDigit(_) => "not a valid integer", - IntErrorKind::NegOverflow => bug!("`limit` should never underflow"), + IntErrorKind::InvalidDigit => "not a valid integer", + IntErrorKind::NegOverflow => { + bug!("`limit` should never negatively underflow") + } IntErrorKind::Zero => bug!("zero is a valid `limit`"), kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), }; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 63ca6e517d214..d67ad30e123f9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -151,6 +151,7 @@ #![feature(slice_ptr_get)] #![feature(no_niche)] // rust-lang/rust#68303 #![feature(unsafe_block_in_unsafe_fn)] +#![feature(int_error_matching)] #![deny(unsafe_op_in_unsafe_fn)] #[prelude_import] diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index e1684719ab4ec..9d8c8c862911c 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -77,20 +77,26 @@ pub struct ParseIntError { /// # Example /// /// ``` +/// #![feature(int_error_matching)] +/// /// # fn main() { /// if let Err(e) = i32::from_str_radix("a12", 10) { /// println!("Failed conversion to i32: {:?}", e.kind()); /// } /// # } /// ``` -#[stable(feature = "int_error_matching", since = "1.47.0")] +#[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" +)] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { /// Value being parsed is empty. /// /// Among other causes, this variant will be constructed when parsing an empty string. - #[stable(feature = "int_error_matching", since = "1.47.0")] Empty, /// Contains an invalid digit in its context. /// @@ -99,25 +105,26 @@ pub enum IntErrorKind { /// /// This variant is also constructed when a `+` or `-` is misplaced within a string /// either on its own or in the middle of a number. - #[stable(feature = "int_error_matching", since = "1.47.0")] - InvalidDigit(#[stable(feature = "int_error_matching", since = "1.47.0")] char), + InvalidDigit, /// Integer is too large to store in target integer type. - #[stable(feature = "int_error_matching", since = "1.47.0")] PosOverflow, /// Integer is too small to store in target integer type. - #[stable(feature = "int_error_matching", since = "1.47.0")] NegOverflow, /// Value was Zero /// /// This variant will be emitted when the parsing string has a value of zero, which /// would be illegal for non-zero types. - #[stable(feature = "int_error_matching", since = "1.47.0")] Zero, } impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. - #[stable(feature = "int_error_matching", since = "1.47.0")] + #[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" + )] pub fn kind(&self) -> &IntErrorKind { &self.kind } @@ -131,7 +138,7 @@ impl ParseIntError { pub fn __description(&self) -> &str { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", - IntErrorKind::InvalidDigit(_) => "invalid digit found in string", + IntErrorKind::InvalidDigit => "invalid digit found in string", IntErrorKind::PosOverflow => "number too large to fit in target type", IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index fd00a072d896c..71448a622c09e 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -63,7 +63,12 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No #[stable(feature = "try_from", since = "1.34.0")] pub use error::TryFromIntError; -#[stable(feature = "int_error_matching", since = "1.47.0")] +#[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" +)] pub use error::IntErrorKind; macro_rules! usize_isize_to_xe_bytes_doc { @@ -831,7 +836,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par let (is_positive, digits) = match src[0] { b'+' | b'-' if src[1..].is_empty() => { - return Err(PIE { kind: InvalidDigit(src[0] as char) }); + return Err(PIE { kind: InvalidDigit }); } b'+' => (true, &src[1..]), b'-' if is_signed_ty => (false, &src[1..]), @@ -844,7 +849,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par for &c in digits { let x = match (c as char).to_digit(radix) { Some(x) => x, - None => return Err(PIE { kind: InvalidDigit(c as char) }), + None => return Err(PIE { kind: InvalidDigit }), }; result = match result.checked_mul(radix) { Some(result) => result, @@ -860,7 +865,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par for &c in digits { let x = match (c as char).to_digit(radix) { Some(x) => x, - None => return Err(PIE { kind: InvalidDigit(c as char) }), + None => return Err(PIE { kind: InvalidDigit }), }; result = match result.checked_mul(radix) { Some(result) => result, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c128691fa7525..d8b36beb3e085 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -37,6 +37,7 @@ #![feature(try_trait)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] +#![feature(int_error_matching)] #![feature(array_value_iter)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index 949d4ea32f064..fb1293c99bba9 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -131,7 +131,7 @@ fn test_from_str() { assert_eq!("0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), Some(IntErrorKind::Zero)); assert_eq!( "-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), - Some(IntErrorKind::InvalidDigit('-')) + Some(IntErrorKind::InvalidDigit) ); assert_eq!( "-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()), diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 12e52252278c5..7c25c32fb40a7 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -118,14 +118,14 @@ fn test_leading_plus() { #[test] fn test_invalid() { - test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit('-'))); - test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit('+'))); - test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit('Ð'))); - test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit('H'))); - test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit('-'))); - test_parse::<i8>("-", Err(IntErrorKind::InvalidDigit('-'))); - test_parse::<i8>("+", Err(IntErrorKind::InvalidDigit('+'))); - test_parse::<u8>("-1", Err(IntErrorKind::InvalidDigit('-'))); + test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("-", Err(IntErrorKind::InvalidDigit)); + test_parse::<i8>("+", Err(IntErrorKind::InvalidDigit)); + test_parse::<u8>("-1", Err(IntErrorKind::InvalidDigit)); } #[test] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index fa23229066cf1..ac0075ad129c5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -264,6 +264,7 @@ #![feature(global_asm)] #![feature(hashmap_internals)] #![feature(int_error_internals)] +#![feature(int_error_matching)] #![feature(integer_atomics)] #![feature(into_future)] #![feature(lang_items)] diff --git a/library/std/src/num.rs b/library/std/src/num.rs index ac3b055cdb050..0f1c596268594 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -22,7 +22,12 @@ pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, #[stable(feature = "nonzero", since = "1.28.0")] pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; -#[stable(feature = "int_error_matching", since = "1.47.0")] +#[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" +)] pub use core::num::IntErrorKind; #[cfg(test)] From e750238404f59f3f6d94142f3e12ffc4c5c0b366 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Mon, 26 Oct 2020 18:16:25 +0000 Subject: [PATCH 19/34] Fix typo --- compiler/rustc_middle/src/middle/limits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index 9ff2b7f08fe04..41342764ba773 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -52,7 +52,7 @@ fn update_limit( IntErrorKind::Empty => "`limit` must be a non-negative integer", IntErrorKind::InvalidDigit => "not a valid integer", IntErrorKind::NegOverflow => { - bug!("`limit` should never negatively underflow") + bug!("`limit` should never negatively overflow") } IntErrorKind::Zero => bug!("zero is a valid `limit`"), kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), From e099138eb6274b8450fbbb3c1fec0389337eb992 Mon Sep 17 00:00:00 2001 From: Stein Somers <git@steinsomers.be> Date: Mon, 26 Oct 2020 23:31:45 +0100 Subject: [PATCH 20/34] BTreeMap: stop mistaking node for an orderly place --- .../alloc/src/collections/btree/map/tests.rs | 26 +++++++++++-- .../alloc/src/collections/btree/node/tests.rs | 37 ------------------- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index adb94972f5bb6..f6921e67636d9 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -42,7 +42,7 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T> } } -impl<'a, K: 'a, V: 'a> BTreeMap<K, V> { +impl<K, V> BTreeMap<K, V> { /// Panics if the map (or the code navigating it) is corrupted. fn check(&self) where @@ -54,14 +54,14 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> { assert!(root_node.ascend().is_err()); root_node.assert_back_pointers(); - let counted = root_node.assert_ascending(); - assert_eq!(self.length, counted); assert_eq!(self.length, root_node.calc_length()); root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 }); } else { assert_eq!(self.length, 0); } + + self.assert_ascending(); } /// Returns the height of the root, if any. @@ -79,10 +79,28 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> { String::from("not yet allocated") } } + + /// Asserts that the keys are in strictly ascending order. + fn assert_ascending(&self) + where + K: Copy + Debug + Ord, + { + let mut num_seen = 0; + let mut keys = self.keys(); + if let Some(mut previous) = keys.next() { + num_seen = 1; + for next in keys { + assert!(previous < next, "{:?} >= {:?}", previous, next); + previous = next; + num_seen += 1; + } + } + assert_eq!(num_seen, self.len()); + } } impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> { - pub fn assert_min_len(self, min_len: usize) { + fn assert_min_len(self, min_len: usize) { assert!(self.len() >= min_len, "{} < {}", self.len(), min_len); if let node::ForceResult::Internal(node) = self.force() { for idx in 0..=node.len() { diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index d6527057c5d77..38c75de34eeeb 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -17,43 +17,6 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> } } - /// Asserts that the keys are in strictly ascending order. - /// Returns how many keys it encountered. - pub fn assert_ascending(self) -> usize - where - K: Copy + Debug + Ord, - { - struct SeriesChecker<T> { - num_seen: usize, - previous: Option<T>, - } - impl<T: Copy + Debug + Ord> SeriesChecker<T> { - fn is_ascending(&mut self, next: T) { - if let Some(previous) = self.previous { - assert!(previous < next, "{:?} >= {:?}", previous, next); - } - self.previous = Some(next); - self.num_seen += 1; - } - } - - let mut checker = SeriesChecker { num_seen: 0, previous: None }; - self.visit_nodes_in_order(|pos| match pos { - navigate::Position::Leaf(node) => { - for idx in 0..node.len() { - let key = *unsafe { node.key_at(idx) }; - checker.is_ascending(key); - } - } - navigate::Position::InternalKV(kv) => { - let key = *kv.into_kv().0; - checker.is_ascending(key); - } - navigate::Position::Internal(_) => {} - }); - checker.num_seen - } - pub fn dump_keys(self) -> String where K: Debug, From b0df3f76dc70eba57d6e0665fa6ccac89b25d3aa Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Wed, 28 Oct 2020 09:05:45 +0100 Subject: [PATCH 21/34] fix some incorrect aliasing in the BTree --- library/alloc/src/collections/btree/node.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index c8d3de9e5cd5c..433074027e7f7 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1608,15 +1608,19 @@ pub mod marker { unsafe fn slice_insert<T>(slice: &mut [T], idx: usize, val: T) { unsafe { - ptr::copy(slice.as_ptr().add(idx), slice.as_mut_ptr().add(idx + 1), slice.len() - idx); - ptr::write(slice.get_unchecked_mut(idx), val); + let len = slice.len(); + let slice_ptr = slice.as_mut_ptr(); + ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx); + ptr::write(slice_ptr.add(idx), val); } } unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T { unsafe { - let ret = ptr::read(slice.get_unchecked(idx)); - ptr::copy(slice.as_ptr().add(idx + 1), slice.as_mut_ptr().add(idx), slice.len() - idx - 1); + let len = slice.len(); + let slice_ptr = slice.as_mut_ptr(); + let ret = ptr::read(slice_ptr.add(idx)); + ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); ret } } From 39103ced582f1111af41326f904966aedd8bc47f Mon Sep 17 00:00:00 2001 From: bjorn3 <bjorn3@users.noreply.github.com> Date: Tue, 3 Nov 2020 16:55:33 +0100 Subject: [PATCH 22/34] Fix run-make tests running when LLVM is disabled --- src/bootstrap/test.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 6c2c05ac7197e..97aad8ed646e8 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1203,17 +1203,6 @@ note: if you're sure you want to do this, please open an issue as to why. In the // Only pass correct values for these flags for the `run-make` suite as it // requires that a C++ compiler was configured which isn't always the case. if !builder.config.dry_run && matches!(suite, "run-make" | "run-make-fulldeps") { - cmd.arg("--cc") - .arg(builder.cc(target)) - .arg("--cxx") - .arg(builder.cxx(target).unwrap()) - .arg("--cflags") - .arg(builder.cflags(target, GitRepo::Rustc).join(" ")); - copts_passed = true; - if let Some(ar) = builder.ar(target) { - cmd.arg("--ar").arg(ar); - } - // The llvm/bin directory contains many useful cross-platform // tools. Pass the path to run-make tests so they can use them. let llvm_bin_path = llvm_config @@ -1239,6 +1228,21 @@ note: if you're sure you want to do this, please open an issue as to why. In the } } + // Only pass correct values for these flags for the `run-make` suite as it + // requires that a C++ compiler was configured which isn't always the case. + if !builder.config.dry_run && matches!(suite, "run-make" | "run-make-fulldeps") { + cmd.arg("--cc") + .arg(builder.cc(target)) + .arg("--cxx") + .arg(builder.cxx(target).unwrap()) + .arg("--cflags") + .arg(builder.cflags(target, GitRepo::Rustc).join(" ")); + copts_passed = true; + if let Some(ar) = builder.ar(target) { + cmd.arg("--ar").arg(ar); + } + } + if !llvm_components_passed { cmd.arg("--llvm-components").arg(""); } From 5fc22f1431e209610040d92ba671966ab2781f0b Mon Sep 17 00:00:00 2001 From: Casey Rodarmor <casey@rodarmor.com> Date: Sun, 1 Nov 2020 19:43:51 -0800 Subject: [PATCH 23/34] Add a tool to run `x.py` from any subdirectory This adds a binary called `x` in `src/tools/x`. All it does is check the current directory and its ancestors for a file called `x.py`, and if it finds one, runs it. By installing x, you can easily `x.py` from any subdirectory. It can be installed globally with `cargo install --path src/tools/x` --- .gitignore | 1 + Cargo.toml | 6 +++ src/tools/x/Cargo.lock | 5 +++ src/tools/x/Cargo.toml | 7 ++++ src/tools/x/README.md | 3 ++ src/tools/x/src/main.rs | 92 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 src/tools/x/Cargo.lock create mode 100644 src/tools/x/Cargo.toml create mode 100644 src/tools/x/README.md create mode 100644 src/tools/x/src/main.rs diff --git a/.gitignore b/.gitignore index 1c50d9b054ddc..5f7135e38d113 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ __pycache__/ /inst/ /llvm/ /mingw-build/ +/src/tools/x/target # Created by default with `src/ci/docker/run.sh`: /obj/ /unicode-downloads diff --git a/Cargo.toml b/Cargo.toml index 02794d1028b50..38fd72ace5385 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,10 +29,16 @@ members = [ "src/tools/unicode-table-generator", "src/tools/expand-yaml-anchors", ] + exclude = [ "build", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", + # The `x` binary is a thin wrapper that calls `x.py`, which initializes + # submodules, before which workspace members cannot be invoked because + # not all `Cargo.toml` files are available, so we exclude the `x` binary, + # so it can be invoked before the current checkout is set up. + "src/tools/x", ] [profile.release.package.compiler_builtins] diff --git a/src/tools/x/Cargo.lock b/src/tools/x/Cargo.lock new file mode 100644 index 0000000000000..723d6cb25ed6a --- /dev/null +++ b/src/tools/x/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "x" +version = "0.1.0" diff --git a/src/tools/x/Cargo.toml b/src/tools/x/Cargo.toml new file mode 100644 index 0000000000000..72c4948c617fa --- /dev/null +++ b/src/tools/x/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "x" +version = "0.1.0" +description = "Run x.py slightly more conveniently" +authors = ["Casey Rodarmor <casey@rodarmor.com>"] +edition = "2018" +publish = false diff --git a/src/tools/x/README.md b/src/tools/x/README.md new file mode 100644 index 0000000000000..3b3cf2847c200 --- /dev/null +++ b/src/tools/x/README.md @@ -0,0 +1,3 @@ +# x + +`x` invokes `x.py` from any subdirectory. diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs new file mode 100644 index 0000000000000..6c0311433d676 --- /dev/null +++ b/src/tools/x/src/main.rs @@ -0,0 +1,92 @@ +//! Run `x.py` from any subdirectory of a rust compiler checkout. +//! +//! We prefer `exec`, to avoid adding an extra process in the process tree. +//! However, since `exec` isn't available on Windows, we indirect through +//! `exec_or_status`, which will call `exec` on unix and `status` on Windows. +//! +//! We use `python`, `python3`, or `python2` as the python interpreter to run +//! `x.py`, in that order of preference. + +use std::{ + env, io, + process::{self, Command, ExitStatus}, +}; + +const PYTHON: &str = "python"; +const PYTHON2: &str = "python2"; +const PYTHON3: &str = "python3"; + +fn python() -> &'static str { + let val = match env::var_os("PATH") { + Some(val) => val, + None => return PYTHON, + }; + + let mut python2 = false; + let mut python3 = false; + + for dir in env::split_paths(&val) { + if dir.join(PYTHON).exists() { + return PYTHON; + } + + python2 |= dir.join(PYTHON2).exists(); + python3 |= dir.join(PYTHON3).exists(); + } + + if python3 { + PYTHON3 + } else if python2 { + PYTHON2 + } else { + PYTHON + } +} + +#[cfg(unix)] +fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> { + use std::os::unix::process::CommandExt; + Err(command.exec()) +} + +#[cfg(not(unix))] +fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> { + command.status() +} + +fn main() { + let current = match env::current_dir() { + Ok(dir) => dir, + Err(err) => { + eprintln!("Failed to get current directory: {}", err); + process::exit(1); + } + }; + + for dir in current.ancestors() { + let candidate = dir.join("x.py"); + + if candidate.exists() { + let mut python = Command::new(python()); + + python.arg(&candidate).args(env::args().skip(1)).current_dir(dir); + + let result = exec_or_status(&mut python); + + match result { + Err(error) => { + eprintln!("Failed to invoke `{}`: {}", candidate.display(), error); + } + Ok(status) => { + process::exit(status.code().unwrap_or(1)); + } + } + } + } + + eprintln!( + "x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`." + ); + + process::exit(1); +} From 54a0a98347f739ee3b9cad8760e237fa6cd8db54 Mon Sep 17 00:00:00 2001 From: Pietro Albini <pietro@pietroalbini.org> Date: Thu, 22 Oct 2020 12:06:12 +0200 Subject: [PATCH 24/34] ci: gate on aarch64-gnu passing tests --- .github/workflows/ci.yml | 115 ++--------------------------------- src/ci/github-actions/ci.yml | 20 +----- 2 files changed, 8 insertions(+), 127 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91241d2b214f9..90296ec32eeda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,6 +154,11 @@ jobs: strategy: matrix: include: + - name: aarch64-gnu + os: + - self-hosted + - ARM64 + - linux - name: arm-android os: ubuntu-latest-xl env: {} @@ -509,116 +514,6 @@ jobs: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" - auto-fallible: - name: auto-fallible - env: - CI_JOB_NAME: "${{ matrix.name }}" - SCCACHE_BUCKET: rust-lang-gha-caches - DEPLOY_BUCKET: rust-lang-gha - TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" - TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF - CACHE_DOMAIN: ci-caches-gha.rust-lang.org - if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - strategy: - fail-fast: false - matrix: - include: - - name: aarch64-gnu - os: - - self-hosted - - ARM64 - - linux - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" - steps: - - name: disable git crlf conversion - run: git config --global core.autocrlf false - - name: checkout the source code - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - name: configure the PR in which the error message will be posted - run: "echo \"[CI_PR_NUMBER=$num]\"" - env: - num: "${{ github.event.number }}" - if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'" - - name: add extra environment variables - run: src/ci/scripts/setup-environment.sh - env: - EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" - if: success() && !env.SKIP_JOB - - name: decide whether to skip this job - run: src/ci/scripts/should-skip-this.sh - if: success() && !env.SKIP_JOB - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - - name: collect CPU statistics - run: src/ci/scripts/collect-cpu-stats.sh - if: success() && !env.SKIP_JOB - - name: show the current environment - run: src/ci/scripts/dump-environment.sh - if: success() && !env.SKIP_JOB - - name: install awscli - run: src/ci/scripts/install-awscli.sh - if: success() && !env.SKIP_JOB - - name: install sccache - run: src/ci/scripts/install-sccache.sh - if: success() && !env.SKIP_JOB - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - if: success() && !env.SKIP_JOB - - name: install clang - run: src/ci/scripts/install-clang.sh - if: success() && !env.SKIP_JOB - - name: install WIX - run: src/ci/scripts/install-wix.sh - if: success() && !env.SKIP_JOB - - name: ensure the build happens on a partition with enough space - run: src/ci/scripts/symlink-build-dir.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - if: success() && !env.SKIP_JOB - - name: install MinGW - run: src/ci/scripts/install-mingw.sh - if: success() && !env.SKIP_JOB - - name: install ninja - run: src/ci/scripts/install-ninja.sh - if: success() && !env.SKIP_JOB - - name: enable ipv6 on Docker - run: src/ci/scripts/enable-docker-ipv6.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: checkout submodules - run: src/ci/scripts/checkout-submodules.sh - if: success() && !env.SKIP_JOB - - name: ensure line endings are correct - run: src/ci/scripts/verify-line-endings.sh - if: success() && !env.SKIP_JOB - - name: run the build - run: src/ci/scripts/run-build-from-ci.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" - TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" - if: success() && !env.SKIP_JOB - - name: upload artifacts to S3 - run: src/ci/scripts/upload-artifacts.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" - if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" try: name: try env: diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 0df191f8f7404..1e28b5a253655 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -301,6 +301,9 @@ jobs: # Linux/Docker builders # ############################# + - name: aarch64-gnu + <<: *job-aarch64-linux + - name: arm-android <<: *job-linux-xl @@ -653,23 +656,6 @@ jobs: SCRIPT: python x.py dist <<: *job-windows-xl - auto-fallible: - <<: *base-ci-job - name: auto-fallible - env: - <<: [*shared-ci-variables, *dummy-variables] - if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' - strategy: - fail-fast: false - matrix: - include: - ############################# - # Linux/Docker builders # - ############################# - - - name: aarch64-gnu - <<: *job-aarch64-linux - try: <<: *base-ci-job name: try From 1274faed1a1379bb1521ae9884bc8ef420971636 Mon Sep 17 00:00:00 2001 From: Pietro Albini <pietro@pietroalbini.org> Date: Thu, 22 Oct 2020 12:23:18 +0200 Subject: [PATCH 25/34] doc/rustc: promote aarch64-unknown-linux-gnu to tier 1 This also adds a note about missing stack probes support, per the discussion on RFC 2959. --- src/doc/rustc/src/platform-support.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 85c6f91f08582..8005a5f3563bf 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -34,6 +34,7 @@ Specifically they will each satisfy the following requirements: target | std | host | notes -------|-----|------|------- +`aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17+) [^missing-stack-probes] `i686-pc-windows-gnu` | ✓ | ✓ | 32-bit MinGW (Windows 7+) `i686-pc-windows-msvc` | ✓ | ✓ | 32-bit MSVC (Windows 7+) `i686-unknown-linux-gnu` | ✓ | ✓ | 32-bit Linux (kernel 2.6.32+, glibc 2.11+) @@ -42,6 +43,12 @@ target | std | host | notes `x86_64-pc-windows-msvc` | ✓ | ✓ | 64-bit MSVC (Windows 7+) `x86_64-unknown-linux-gnu` | ✓ | ✓ | 64-bit Linux (kernel 2.6.32+, glibc 2.11+) +[^missing-stack-probes]: Stack probes support is missing on + `aarch64-unknown-linux-gnu`, but it's planned to be implemented in the near + future. The implementation is tracked on [issue #77071][77071]. + +[77071]: https://github.com/rust-lang/rust/issues/77071 + ## Tier 2 Tier 2 platforms can be thought of as "guaranteed to build". Automated tests @@ -62,7 +69,6 @@ target | std | host | notes `aarch64-fuchsia` | ✓ | | ARM64 Fuchsia `aarch64-linux-android` | ✓ | | ARM64 Android `aarch64-pc-windows-msvc` | ✓ | ✓ | ARM64 Windows MSVC -`aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17) `aarch64-unknown-linux-musl` | ✓ | ✓ | ARM64 Linux with MUSL `aarch64-unknown-none` | * | | Bare ARM64, hardfloat `aarch64-unknown-none-softfloat` | * | | Bare ARM64, softfloat From 874cbb88e0379a0e7bab5b9db99e2a4c495534fb Mon Sep 17 00:00:00 2001 From: Pietro Albini <pietro@pietroalbini.org> Date: Thu, 22 Oct 2020 12:31:11 +0200 Subject: [PATCH 26/34] ci: build docs for aarch64-unknown-linux-gnu --- src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile | 3 +-- src/tools/build-manifest/src/main.rs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile index df65f9df44127..95c54ca1abc06 100644 --- a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile @@ -35,6 +35,5 @@ ENV HOSTS=aarch64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-profiler \ - --enable-sanitizers \ - --disable-docs + --enable-sanitizers ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 9a8f2404e4a1a..687354dc6aee2 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -155,6 +155,7 @@ static TARGETS: &[&str] = &[ ]; static DOCS_TARGETS: &[&str] = &[ + "aarch64-unknown-linux-gnu", "i686-apple-darwin", "i686-pc-windows-gnu", "i686-pc-windows-msvc", From eed0cebea3d16d82f5517e17ab498b340001fe01 Mon Sep 17 00:00:00 2001 From: Joshua Nelson <jyn514@gmail.com> Date: Mon, 19 Oct 2020 14:20:14 -0400 Subject: [PATCH 27/34] Recognize `private_intra_doc_links` as a lint Previously, trying to allow this would give another error! ``` warning: unknown lint: `private_intra_doc_links` --> private.rs:1:10 | 1 | #![allow(private_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `broken_intra_doc_links` | = note: `#[warn(unknown_lints)]` on by default warning: public documentation for `DocMe` links to private item `DontDocMe` --> private.rs:2:11 | 2 | /// docs [DontDocMe] | ^^^^^^^^^ this item is private | = note: `#[warn(private_intra_doc_links)]` on by default = note: this link will resolve properly if you pass `--document-private-items` ``` --- compiler/rustc_lint_defs/src/builtin.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a1b7c13e4c0f0..7176a66cdc1bd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2790,6 +2790,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, BROKEN_INTRA_DOC_LINKS, + PRIVATE_INTRA_DOC_LINKS, INVALID_CODEBLOCK_ATTRIBUTES, MISSING_CRATE_LEVEL_DOCS, MISSING_DOC_CODE_EXAMPLES, From 47b21b84f3ed88cff31fccc78a57a66241a26496 Mon Sep 17 00:00:00 2001 From: Joshua Nelson <jyn514@gmail.com> Date: Thu, 5 Nov 2020 13:11:50 -0500 Subject: [PATCH 28/34] Add PRIVATE_INTRA_DOC_LINKS to rustdoc special-casing This is really starting to get out of hand. Rustdoc should instead allow all lints in the rustdoc lint group. --- src/librustdoc/core.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 45a84c4fb30d3..285a3bf8204bb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -322,7 +322,8 @@ pub fn run_core( let cpath = Some(input.clone()); let input = Input::File(input); - let intra_link_resolution_failure_name = lint::builtin::BROKEN_INTRA_DOC_LINKS.name; + let broken_intra_doc_links = lint::builtin::BROKEN_INTRA_DOC_LINKS.name; + let private_intra_doc_links = lint::builtin::PRIVATE_INTRA_DOC_LINKS.name; let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; @@ -335,7 +336,8 @@ pub fn run_core( // In addition to those specific lints, we also need to allow those given through // command line, otherwise they'll get ignored and we don't want that. let lints_to_show = vec![ - intra_link_resolution_failure_name.to_owned(), + broken_intra_doc_links.to_owned(), + private_intra_doc_links.to_owned(), missing_docs.to_owned(), missing_doc_example.to_owned(), private_doc_tests.to_owned(), @@ -347,9 +349,8 @@ pub fn run_core( ]; let (lint_opts, lint_caps) = init_lints(lints_to_show, lint_opts, |lint| { - if lint.name == intra_link_resolution_failure_name - || lint.name == invalid_codeblock_attributes_name - { + // FIXME: why is this necessary? + if lint.name == broken_intra_doc_links || lint.name == invalid_codeblock_attributes_name { None } else { Some((lint.name_lower(), lint::Allow)) From dd68d0b28d4265fba1b7692f3f4357821e4e8de2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner <a.beingessner@gmail.com> Date: Thu, 5 Nov 2020 17:18:14 -0500 Subject: [PATCH 29/34] Vendor libtest's dependencies in the rust-src component This is the Rust side of https://github.com/rust-lang/wg-cargo-std-aware/issues/23 --- src/bootstrap/dist.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bdab12db43502..4534c69d40de9 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1040,6 +1040,25 @@ impl Step for Src { builder.copy(&builder.src.join(file), &dst_src.join(file)); } + // libtest includes std and everything else, so vendoring it + // creates exactly what's needed for `cargo -Zbuild-std` or any + // other analysis of the stdlib's source. Cargo also needs help + // finding the lock, so we copy it to libtest temporarily. + // + // Note that this requires std to only have one version of each + // crate. e.g. two versions of getopts won't be patchable. + let dst_libtest = dst_src.join("library/test"); + let dst_vendor = dst_src.join("vendor"); + let root_lock = dst_src.join("Cargo.lock"); + let temp_lock = dst_libtest.join("Cargo.lock"); + builder.copy(&root_lock, &temp_lock); + + let mut cmd = Command::new(&builder.initial_cargo); + cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libtest); + builder.run(&mut cmd); + + builder.remove(&temp_lock); + // Create source tarball in rust-installer format let mut cmd = rust_installer(builder); cmd.arg("generate") From e8b5be5dffef9ef6a15a085e4b06c4a0471f360d Mon Sep 17 00:00:00 2001 From: Ivan Tham <pickfire@riseup.net> Date: Sun, 30 Aug 2020 10:35:50 +0800 Subject: [PATCH 30/34] Stabilize hint::spin_loop Partially fix #55002, deprecate in another release Co-authored-by: Ashley Mannix <kodraus@hey.com> Update stable version for stabilize_spin_loop Co-authored-by: Joshua Nelson <joshua@yottadb.com> Use better example for spinlock As suggested by KodrAus Remove renamed_spin_loop already available in master Fix spin loop example --- library/alloc/src/lib.rs | 1 - library/core/src/hint.rs | 62 ++++++++++++++++++++++++++++----- library/core/src/sync/atomic.rs | 16 ++------- library/std/src/lib.rs | 1 - 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 0fe15958076c5..ccabc336acc16 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -119,7 +119,6 @@ #![feature(raw_ref_op)] #![feature(rustc_attrs)] #![feature(receiver_trait)] -#![feature(renamed_spin_loop)] #![feature(min_specialization)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 454fb34e77e49..979a5f8cf5075 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -1,6 +1,7 @@ #![stable(feature = "core_hint", since = "1.27.0")] //! Hints to compiler that affects how code should be emitted or optimized. +//! Hints may be compile time or runtime. use crate::intrinsics; @@ -24,7 +25,6 @@ use crate::intrinsics; /// Otherwise, consider using the [`unreachable!`] macro, which does not allow /// optimizations but will panic when executed. /// -/// /// # Example /// /// ``` @@ -51,18 +51,62 @@ pub const unsafe fn unreachable_unchecked() -> ! { unsafe { intrinsics::unreachable() } } -/// Emits a machine instruction hinting to the processor that it is running in busy-wait -/// spin-loop ("spin lock"). +/// Emits a machine instruction to signal the processor that it is running in +/// a busy-wait spin-loop ("spin lock"). +/// +/// Upon receiving the spin-loop signal the processor can optimize its behavior by, +/// for example, saving power or switching hyper-threads. +/// +/// This function is different from [`thread::yield_now`] which directly +/// yields to the system's scheduler, whereas `spin_loop` does not interact +/// with the operating system. +/// +/// A common use case for `spin_loop` is implementing bounded optimistic +/// spinning in a CAS loop in synchronization primitives. To avoid problems +/// like priority inversion, it is strongly recommended that the spin loop is +/// terminated after a finite amount of iterations and an appropriate blocking +/// syscall is made. +/// +/// **Note**: On platforms that do not support receiving spin-loop hints this +/// function does not do anything at all. +/// +/// # Examples /// -/// For a discussion of different locking strategies and their trade-offs, see -/// [`core::sync::atomic::spin_loop_hint`]. +/// ``` +/// use std::sync::atomic::{AtomicBool, Ordering}; +/// use std::sync::Arc; +/// use std::{hint, thread}; +/// +/// // A shared atomic value that threads will use to coordinate +/// let live = Arc::new(AtomicBool::new(false)); +/// +/// // In a background thread we'll eventually set the value +/// let bg_work = { +/// let live = live.clone(); +/// thread::spawn(move || { +/// // Do some work, then make the value live +/// do_some_work(); +/// live.store(true, Ordering::Release); +/// }) +/// }; /// -/// **Note**: On platforms that do not support receiving spin-loop hints this function does not -/// do anything at all. +/// // Back on our current thread, we wait for the value to be set +/// while live.load(Ordering::Acquire) { +/// // The spin loop is a hint to the CPU that we're waiting, but probably +/// // not for very long +/// hint::spin_loop(); +/// } +/// +/// // The value is now set +/// # fn do_some_work() {} +/// do_some_work(); +/// bg_work.join()?; +/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(()) +/// ``` /// -/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint +/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html #[inline] -#[unstable(feature = "renamed_spin_loop", issue = "55002")] +#[stable(feature = "renamed_spin_loop", since = "1.49.0")] pub fn spin_loop() { #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))] { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5c9cfe27101f0..5dbea6e71aa4f 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -115,23 +115,13 @@ use crate::hint::spin_loop; /// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). /// -/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving -/// power or switching hyper-threads. -/// -/// This function is different from [`std::thread::yield_now`] which directly yields to the -/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system. -/// -/// A common use case for `spin_loop_hint` is implementing bounded optimistic spinning in a CAS -/// loop in synchronization primitives. To avoid problems like priority inversion, it is strongly -/// recommended that the spin loop is terminated after a finite amount of iterations and an -/// appropriate blocking syscall is made. +/// This function is expected to be deprecated in favor of +/// [`hint::spin_loop`]. /// /// **Note**: On platforms that do not support receiving spin-loop hints this function does not /// do anything at all. /// -/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html -/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html -/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html +/// [`hint::spin_loop`]: crate::hint::spin_loop #[inline] #[stable(feature = "spin_loop_hint", since = "1.24.0")] pub fn spin_loop_hint() { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 96a7755c68821..1636fe5e2575a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -296,7 +296,6 @@ #![feature(raw)] #![feature(raw_ref_macros)] #![feature(ready_macro)] -#![feature(renamed_spin_loop)] #![feature(rustc_attrs)] #![feature(rustc_private)] #![feature(shrink_to)] From 020ed653a374d9b8ffa29d191839c1d49a7ce656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sat, 7 Nov 2020 01:23:02 +0100 Subject: [PATCH 31/34] use single char patterns for split() (clippy::single_char_pattern) --- compiler/rustc_mir/src/transform/coverage/debug.rs | 8 ++++---- compiler/rustc_mir/src/util/generic_graphviz.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index cc697dfd7fe28..ffa795134e257 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -147,8 +147,8 @@ impl DebugOptions { let mut counter_format = ExpressionFormat::default(); if let Ok(env_debug_options) = std::env::var(RUSTC_COVERAGE_DEBUG_OPTIONS) { - for setting_str in env_debug_options.replace(" ", "").replace("-", "_").split(",") { - let mut setting = setting_str.splitn(2, "="); + for setting_str in env_debug_options.replace(" ", "").replace("-", "_").split(',') { + let mut setting = setting_str.splitn(2, '='); match setting.next() { Some(option) if option == "allow_unused_expressions" => { allow_unused_expressions = bool_option_val(option, setting.next()); @@ -210,7 +210,7 @@ fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool { fn counter_format_option_val(strval: &str) -> ExpressionFormat { let mut counter_format = ExpressionFormat { id: false, block: false, operation: false }; - let components = strval.splitn(3, "+"); + let components = strval.splitn(3, '+'); for component in components { match component { "id" => counter_format.id = true, @@ -695,7 +695,7 @@ pub(crate) fn dump_coverage_graphviz( let from_bcb_data = &basic_coverage_blocks[from_bcb]; let from_terminator = from_bcb_data.terminator(mir_body); let mut edge_labels = from_terminator.kind.fmt_successor_labels(); - edge_labels.retain(|label| label.to_string() != "unreachable"); + edge_labels.retain(|label| label != "unreachable"); let edge_counters = from_terminator .successors() .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); diff --git a/compiler/rustc_mir/src/util/generic_graphviz.rs b/compiler/rustc_mir/src/util/generic_graphviz.rs index 91499bb61c287..8bd4a512bbb05 100644 --- a/compiler/rustc_mir/src/util/generic_graphviz.rs +++ b/compiler/rustc_mir/src/util/generic_graphviz.rs @@ -174,7 +174,7 @@ impl< where W: Write, { - let lines = label.split("\n").map(|s| dot::escape_html(s)).collect::<Vec<_>>(); + let lines = label.split('\n').map(|s| dot::escape_html(s)).collect::<Vec<_>>(); let escaped_label = lines.join(r#"<br align="left"/>"#); writeln!(w, r#" label=<<br/><br/>{}<br align="left"/><br/><br/><br/>>;"#, escaped_label) } From 5c8d25f4035d490063abcca8e71e7b602d467e64 Mon Sep 17 00:00:00 2001 From: Daiki Ihara <sasurau4@gmail.com> Date: Sat, 7 Nov 2020 21:34:40 +0900 Subject: [PATCH 32/34] remove FIXME comment of #62277 in print_type_sizez ui tests --- src/test/ui/print_type_sizes/anonymous.rs | 2 +- src/test/ui/print_type_sizes/generics.rs | 2 +- src/test/ui/print_type_sizes/multiple_types.rs | 2 +- src/test/ui/print_type_sizes/niche-filling.rs | 2 +- src/test/ui/print_type_sizes/no_duplicates.rs | 2 +- src/test/ui/print_type_sizes/packed.rs | 2 +- src/test/ui/print_type_sizes/padding.rs | 2 +- src/test/ui/print_type_sizes/repr-align.rs | 2 +- src/test/ui/print_type_sizes/repr_int_c.rs | 2 +- src/test/ui/print_type_sizes/uninhabited.rs | 2 +- src/test/ui/print_type_sizes/variants.rs | 2 +- src/test/ui/print_type_sizes/zero-sized-fields.rs | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs index b96348640fa15..2b008ca3b3a9a 100644 --- a/src/test/ui/print_type_sizes/anonymous.rs +++ b/src/test/ui/print_type_sizes/anonymous.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // All of the types that occur in this function are uninteresting, in // that one cannot control the sizes of these types with the same sort diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs index f165526dffa23..3ef7b60db2cae 100644 --- a/src/test/ui/print_type_sizes/generics.rs +++ b/src/test/ui/print_type_sizes/generics.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs index 4cb7ae03b5406..f1ad27ec13137 100644 --- a/src/test/ui/print_type_sizes/multiple_types.rs +++ b/src/test/ui/print_type_sizes/multiple_types.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // This file illustrates that when multiple structural types occur in // a function, every one of them is included in the output. diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs index d9845fd6d70cc..37ac45f7e053c 100644 --- a/src/test/ui/print_type_sizes/niche-filling.rs +++ b/src/test/ui/print_type_sizes/niche-filling.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs index 4495a7770a760..e45e4794a3526 100644 --- a/src/test/ui/print_type_sizes/no_duplicates.rs +++ b/src/test/ui/print_type_sizes/no_duplicates.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs index dce4a61ef337b..269cc3cc2825f 100644 --- a/src/test/ui/print_type_sizes/packed.rs +++ b/src/test/ui/print_type_sizes/packed.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs index 1f894c5e252fa..d1acad16d7e1d 100644 --- a/src/test/ui/print_type_sizes/padding.rs +++ b/src/test/ui/print_type_sizes/padding.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // This file illustrates how padding is handled: alignment // requirements can lead to the introduction of padding, either before diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs index 1e6f7ccca40f2..07544935b2f82 100644 --- a/src/test/ui/print_type_sizes/repr-align.rs +++ b/src/test/ui/print_type_sizes/repr-align.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs index 7aad2715bc073..b8067c112eef1 100644 --- a/src/test/ui/print_type_sizes/repr_int_c.rs +++ b/src/test/ui/print_type_sizes/repr_int_c.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)` // variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug). diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs index ae4e492456af9..c234547bd14b1 100644 --- a/src/test/ui/print_type_sizes/uninhabited.rs +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. // FIXME: consider using an attribute instead of side-effects. diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs index 77e2b4befba7d..6c8553cc23ded 100644 --- a/src/test/ui/print_type_sizes/variants.rs +++ b/src/test/ui/print_type_sizes/variants.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // This file illustrates two things: // diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.rs b/src/test/ui/print_type_sizes/zero-sized-fields.rs index 71d091677473a..e02a33109e56a 100644 --- a/src/test/ui/print_type_sizes/zero-sized-fields.rs +++ b/src/test/ui/print_type_sizes/zero-sized-fields.rs @@ -1,5 +1,5 @@ // compile-flags: -Z print-type-sizes -// build-pass (FIXME(62277): could be check-pass?) +// build-pass // ignore-pass // At one point, zero-sized fields such as those in this file were causing From 67d0db6b008f98c1a1ba8ed6c267105433250fc9 Mon Sep 17 00:00:00 2001 From: Joshua Nelson <jyn514@gmail.com> Date: Wed, 21 Oct 2020 22:00:32 -0400 Subject: [PATCH 33/34] Fix handling of item names for HIR - Handle variants, fields, macros in `Node::ident()` - Handle the crate root in `opt_item_name` - Factor out `item_name_from_def_id` to reduce duplication - Look at HIR before the DefId for `opt_item_name` This gives accurate spans, which are not available from serialized metadata. - Don't panic on the crate root in `opt_item_name` - Add comments --- compiler/rustc_hir/src/hir.rs | 3 ++ compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 65 ++++++++++++++++-------- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b9ec18688c5f2..3c72937ad3134 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2677,6 +2677,9 @@ impl<'hir> Node<'hir> { Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) | Node::ForeignItem(ForeignItem { ident, .. }) + | Node::Field(StructField { ident, .. }) + | Node::Variant(Variant { ident, .. }) + | Node::MacroDef(MacroDef { ident, .. }) | Node::Item(Item { ident, .. }) => Some(*ident), _ => None, } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 106fa8c78fa28..d86e898719557 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -478,7 +478,7 @@ impl<'hir> Map<'hir> { } pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> { - id.as_local().map(|id| self.get(self.local_def_id_to_hir_id(id))) + id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id))) } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index aa5a696b09c3b..c69dabda54937 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2795,10 +2795,52 @@ impl<'tcx> TyCtxt<'tcx> { .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value()) } + fn item_name_from_hir(self, def_id: DefId) -> Option<Ident> { + self.hir().get_if_local(def_id).and_then(|node| node.ident()) + } + + fn item_name_from_def_id(self, def_id: DefId) -> Option<Symbol> { + if def_id.index == CRATE_DEF_INDEX { + Some(self.original_crate_name(def_id.krate)) + } else { + let def_key = self.def_key(def_id); + match def_key.disambiguated_data.data { + // The name of a constructor is that of its parent. + rustc_hir::definitions::DefPathData::Ctor => self.item_name_from_def_id(DefId { + krate: def_id.krate, + index: def_key.parent.unwrap(), + }), + _ => def_key.disambiguated_data.data.get_opt_name(), + } + } + } + + /// Look up the name of an item across crates. This does not look at HIR. + /// + /// When possible, this function should be used for cross-crate lookups over + /// [`opt_item_name`] to avoid invalidating the incremental cache. If you + /// need to handle items without a name, or HIR items that will not be + /// serialized cross-crate, or if you need the span of the item, use + /// [`opt_item_name`] instead. + /// + /// [`opt_item_name`]: Self::opt_item_name + pub fn item_name(self, id: DefId) -> Symbol { + // Look at cross-crate items first to avoid invalidating the incremental cache + // unless we have to. + self.item_name_from_def_id(id) + .or_else(|| self.item_name_from_hir(id).map(|ident| ident.name)) + .unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) + } + + /// Look up the name and span of an item or [`Node`]. + /// + /// See [`item_name`][Self::item_name] for more information. pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> { - def_id - .as_local() - .and_then(|def_id| self.hir().get(self.hir().local_def_id_to_hir_id(def_id)).ident()) + // Look at the HIR first so the span will be correct if this is a local item. + self.item_name_from_hir(def_id) + .or_else(|| self.item_name_from_def_id(def_id).map(Ident::with_dummy_span)) } pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> { @@ -2921,23 +2963,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn item_name(self, id: DefId) -> Symbol { - if id.index == CRATE_DEF_INDEX { - self.original_crate_name(id.krate) - } else { - let def_key = self.def_key(id); - match def_key.disambiguated_data.data { - // The name of a constructor is that of its parent. - rustc_hir::definitions::DefPathData::Ctor => { - self.item_name(DefId { krate: id.krate, index: def_key.parent.unwrap() }) - } - _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { - bug!("item_name: no name for {:?}", self.def_path(id)); - }), - } - } - } - /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { match instance { From f60fd4963207bd6ac4a1c93c7c2674a7c321ffa8 Mon Sep 17 00:00:00 2001 From: Joshua Nelson <jyn514@gmail.com> Date: Sat, 7 Nov 2020 10:34:00 -0500 Subject: [PATCH 34/34] Remove unused `from_hir` call --- compiler/rustc_middle/src/ty/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c69dabda54937..0042b4a3a4279 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2827,11 +2827,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn item_name(self, id: DefId) -> Symbol { // Look at cross-crate items first to avoid invalidating the incremental cache // unless we have to. - self.item_name_from_def_id(id) - .or_else(|| self.item_name_from_hir(id).map(|ident| ident.name)) - .unwrap_or_else(|| { - bug!("item_name: no name for {:?}", self.def_path(id)); - }) + self.item_name_from_def_id(id).unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) } /// Look up the name and span of an item or [`Node`].