From 36bcbc352d4b48f0f3aea35fd9ca74e856f797c9 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Mon, 25 Feb 2019 07:09:16 +0100 Subject: [PATCH 01/37] Add FromStr impl for NonZero types --- src/libcore/num/mod.rs | 106 +++++++++++++++++++++++++++++++++++ src/libcore/tests/nonzero.rs | 17 ++++++ 2 files changed, 123 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 5b7d5f45d9246..1479b891fa2b6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -112,6 +112,112 @@ nonzero_integers! { #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } +/// An error which can be returned when parsing a non-zero integer. +/// +/// # Potential causes +/// +/// Among other causes, `ParseNonZeroIntError` can be thrown because of leading or trailing +/// whitespace in the string e.g., when it is obtained from the standard input. +/// Using the [`str.trim()`] method ensures that no whitespace remains before parsing. +/// +/// [`str.trim()`]: ../../std/primitive.str.html#method.trim +#[unstable(feature = "nonzero_parse", issue = "0")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseNonZeroIntError { + kind: NonZeroIntErrorKind, +} + +/// Enum to store the various types of errors that can cause parsing a non-zero integer to fail. +#[unstable(feature = "nonzero_parse", issue = "0")] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum NonZeroIntErrorKind { + /// Value being parsed is empty. + /// + /// Among other causes, this variant will be constructed when parsing an empty string. + Empty, + /// Contains an invalid digit. + /// + /// Among other causes, this variant will be constructed when parsing a string that + /// contains a letter. + InvalidDigit, + /// Integer is too large to store in target integer type. + Overflow, + /// Integer is too small to store in target integer type. + Underflow, + /// Integer contains the value `0` which is forbidden for a non-zero integer + Zero, +} + +#[unstable(feature = "nonzero_parse", issue = "0")] +impl From for ParseNonZeroIntError { + fn from(p: ParseIntError) -> Self { + use self::IntErrorKind as IK; + use self::NonZeroIntErrorKind as NK; + ParseNonZeroIntError { + kind: match p.kind { + IK::Empty => NK::Empty, + IK::InvalidDigit => NK::InvalidDigit, + IK::Overflow => NK::Overflow, + IK::Underflow => NK::Underflow, + }, + } + } +} + +impl ParseNonZeroIntError { + /// 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")] + pub fn kind(&self) -> &NonZeroIntErrorKind { + &self.kind + } + + #[unstable(feature = "int_error_internals", + reason = "available through Error trait and this method should \ + not be exposed publicly", + issue = "0")] + #[doc(hidden)] + pub fn __description(&self) -> &str { + match self.kind { + NonZeroIntErrorKind::Empty => "cannot parse integer from empty string", + NonZeroIntErrorKind::InvalidDigit => "invalid digit found in string", + NonZeroIntErrorKind::Overflow => "number too large to fit in target type", + NonZeroIntErrorKind::Underflow => "number too small to fit in target type", + NonZeroIntErrorKind::Zero => "number is 0", + } + } + +} + +#[unstable(feature = "nonzero_parse", issue = "0")] +impl fmt::Display for ParseNonZeroIntError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.__description().fmt(f) + } +} + + +macro_rules! from_str_radix_nzint_impl { + ($($t:ty)*) => {$( + #[unstable(feature = "nonzero_parse", issue = "0")] + impl FromStr for $t { + type Err = ParseNonZeroIntError; + fn from_str(src: &str) -> Result { + Self::new(from_str_radix(src, 10)?) + .ok_or(ParseNonZeroIntError { + kind: NonZeroIntErrorKind::Zero + }) + } + } + )*} +} + +from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize + NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } + /// Provides intentionally-wrapped arithmetic on `T`. /// /// Operations like `+` on `u32` values is intended to never overflow, diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 4532568ee0c16..6e2d4588edc71 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -126,3 +126,20 @@ fn test_from_signed_nonzero() { let num: i32 = nz.into(); assert_eq!(num, 1i32); } + +#[test] +fn test_from_str() { + assert_eq!(FromStr::from_str("123"), Ok(NonZeroU8::new(123).unwrap())); + assert_eq!( + FromStr::from_str("0"), + Err(ParseNonZeroIntError { + kind: NonZeroIntErrorKind::Zero + }) + ); + assert_eq!( + FromStr::from_str("-1", + Err(ParseNonZeroIntError { + kind: NonZeroIntErrorKind::Underflow + }) + ); +} From ce30d4e1b947f8580636909c4c6f5aaeb254ea4c Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Wed, 27 Feb 2019 18:37:35 +0100 Subject: [PATCH 02/37] replaced nonzeroparseerror with regular interror --- src/libcore/num/mod.rs | 102 ++++------------------------------- src/libcore/tests/nonzero.rs | 20 ++++--- 2 files changed, 23 insertions(+), 99 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 1479b891fa2b6..77b709a050d57 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -112,103 +112,15 @@ nonzero_integers! { #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } -/// An error which can be returned when parsing a non-zero integer. -/// -/// # Potential causes -/// -/// Among other causes, `ParseNonZeroIntError` can be thrown because of leading or trailing -/// whitespace in the string e.g., when it is obtained from the standard input. -/// Using the [`str.trim()`] method ensures that no whitespace remains before parsing. -/// -/// [`str.trim()`]: ../../std/primitive.str.html#method.trim -#[unstable(feature = "nonzero_parse", issue = "0")] -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ParseNonZeroIntError { - kind: NonZeroIntErrorKind, -} - -/// Enum to store the various types of errors that can cause parsing a non-zero integer to fail. -#[unstable(feature = "nonzero_parse", issue = "0")] -#[derive(Debug, Clone, PartialEq, Eq)] -#[non_exhaustive] -pub enum NonZeroIntErrorKind { - /// Value being parsed is empty. - /// - /// Among other causes, this variant will be constructed when parsing an empty string. - Empty, - /// Contains an invalid digit. - /// - /// Among other causes, this variant will be constructed when parsing a string that - /// contains a letter. - InvalidDigit, - /// Integer is too large to store in target integer type. - Overflow, - /// Integer is too small to store in target integer type. - Underflow, - /// Integer contains the value `0` which is forbidden for a non-zero integer - Zero, -} - -#[unstable(feature = "nonzero_parse", issue = "0")] -impl From for ParseNonZeroIntError { - fn from(p: ParseIntError) -> Self { - use self::IntErrorKind as IK; - use self::NonZeroIntErrorKind as NK; - ParseNonZeroIntError { - kind: match p.kind { - IK::Empty => NK::Empty, - IK::InvalidDigit => NK::InvalidDigit, - IK::Overflow => NK::Overflow, - IK::Underflow => NK::Underflow, - }, - } - } -} - -impl ParseNonZeroIntError { - /// 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")] - pub fn kind(&self) -> &NonZeroIntErrorKind { - &self.kind - } - - #[unstable(feature = "int_error_internals", - reason = "available through Error trait and this method should \ - not be exposed publicly", - issue = "0")] - #[doc(hidden)] - pub fn __description(&self) -> &str { - match self.kind { - NonZeroIntErrorKind::Empty => "cannot parse integer from empty string", - NonZeroIntErrorKind::InvalidDigit => "invalid digit found in string", - NonZeroIntErrorKind::Overflow => "number too large to fit in target type", - NonZeroIntErrorKind::Underflow => "number too small to fit in target type", - NonZeroIntErrorKind::Zero => "number is 0", - } - } - -} - -#[unstable(feature = "nonzero_parse", issue = "0")] -impl fmt::Display for ParseNonZeroIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.__description().fmt(f) - } -} - - macro_rules! from_str_radix_nzint_impl { ($($t:ty)*) => {$( - #[unstable(feature = "nonzero_parse", issue = "0")] + #[stable(feature = "nonzero_parse", since = "1.35.0")] impl FromStr for $t { - type Err = ParseNonZeroIntError; + type Err = ParseIntError; fn from_str(src: &str) -> Result { Self::new(from_str_radix(src, 10)?) - .ok_or(ParseNonZeroIntError { - kind: NonZeroIntErrorKind::Zero + .ok_or(ParseIntError { + kind: IntErrorKind::Zero }) } } @@ -4968,6 +4880,11 @@ pub enum IntErrorKind { Overflow, /// Integer is too small to store in target integer type. Underflow, + /// 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. + Zero, } impl ParseIntError { @@ -4990,6 +4907,7 @@ impl ParseIntError { 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::Zero => "number would be zero for non-zero type", } } } diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 6e2d4588edc71..764b0c249f9ca 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -129,17 +129,23 @@ fn test_from_signed_nonzero() { #[test] fn test_from_str() { - assert_eq!(FromStr::from_str("123"), Ok(NonZeroU8::new(123).unwrap())); + assert_eq!("123".parse::(), Ok(NonZeroU8::new(123).unwrap())); assert_eq!( - FromStr::from_str("0"), - Err(ParseNonZeroIntError { - kind: NonZeroIntErrorKind::Zero + "0".parse::(), + Err(ParseIntError { + kind: IntErrorKind::Zero }) ); assert_eq!( - FromStr::from_str("-1", - Err(ParseNonZeroIntError { - kind: NonZeroIntErrorKind::Underflow + "-1".parse::(), + Err(ParseIntError { + kind: IntErrorKind::Underflow + }) + ); + assert_eq!( + "129".parse::(), + Err(ParseIntError { + kind: IntErrorKind::Overflow }) ); } From 912ad6831ef0913afb7b0b5b6edc62bf002ebea8 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Feb 2019 07:45:33 +0100 Subject: [PATCH 03/37] fixed nonzero tests --- src/libcore/tests/nonzero.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 764b0c249f9ca..8e2d4177d08c7 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -1,6 +1,5 @@ -use core::num::{NonZeroU32, NonZeroI32}; -use core::option::Option; -use core::option::Option::{Some, None}; +use core::num::{IntErrorKind, NonZeroU8, NonZeroU32, NonZeroI32, ParseIntError}; +use core::option::Option::{self, Some, None}; use std::mem::size_of; #[test] @@ -143,7 +142,7 @@ fn test_from_str() { }) ); assert_eq!( - "129".parse::(), + "257".parse::(), Err(ParseIntError { kind: IntErrorKind::Overflow }) From ad240ea70c2ba4b4a03286320a7909e485507d75 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Feb 2019 14:47:32 +0100 Subject: [PATCH 04/37] add feature flag to test --- src/libcore/tests/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 4cd734bad90a4..6db0d88e35554 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,6 +34,7 @@ #![feature(slice_internals)] #![feature(slice_partition_dedup)] #![feature(copy_within)] +#![feature(int_error_matching)] extern crate core; extern crate test; From 7330525e8fa8e873bc7feeb476fa161d20786a43 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Feb 2019 20:48:08 +0100 Subject: [PATCH 05/37] fixed tests again --- src/libcore/tests/nonzero.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 8e2d4177d08c7..77e484601bc22 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -1,5 +1,5 @@ -use core::num::{IntErrorKind, NonZeroU8, NonZeroU32, NonZeroI32, ParseIntError}; -use core::option::Option::{self, Some, None}; +use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8}; +use core::option::Option::{self, None, Some}; use std::mem::size_of; #[test] @@ -130,21 +130,19 @@ fn test_from_signed_nonzero() { fn test_from_str() { assert_eq!("123".parse::(), Ok(NonZeroU8::new(123).unwrap())); assert_eq!( - "0".parse::(), - Err(ParseIntError { - kind: IntErrorKind::Zero - }) + "0".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) ); assert_eq!( - "-1".parse::(), - Err(ParseIntError { - kind: IntErrorKind::Underflow - }) + "-1".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) ); assert_eq!( - "257".parse::(), - Err(ParseIntError { - kind: IntErrorKind::Overflow - }) + "-129".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::Underflow) + ); + assert_eq!( + "257".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::Overflow) ); } From 8740d5d171fbb2fc9a12e46ecda32a0124badb46 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 20:08:32 +0100 Subject: [PATCH 06/37] Add benchmarks for [u8]::make_ascii_uppercase --- src/libcore/benches/ascii_case.rs | 172 ++++++++++++++++++++++++++++++ src/libcore/benches/lib.rs | 1 + 2 files changed, 173 insertions(+) create mode 100644 src/libcore/benches/ascii_case.rs diff --git a/src/libcore/benches/ascii_case.rs b/src/libcore/benches/ascii_case.rs new file mode 100644 index 0000000000000..43242ca3f364e --- /dev/null +++ b/src/libcore/benches/ascii_case.rs @@ -0,0 +1,172 @@ +// Lower-case ASCII 'a' is the first byte that has its highest bit set after wrap-adding 0x1F: +// +// b'a' + 0x1F == 0x80 == 0b1000_0000 +// b'z' + 0x1F == 0x98 == 0b10011000 +// +// Lower-case ASCII 'z' is the last byte that has its highest bit unset after wrap-adding 0x05: +// +// b'a' + 0x05 == 0x66 == 0b0110_0110 +// b'z' + 0x05 == 0x7F == 0b0111_1111 +// +// … except for 0xFB to 0xFF, but those are in the range of bytes that have the highest bit +// unset again after adding 0x1F. +// +// So `(byte + 0x1f) & !(byte + 5)` has its highest bit set +// iff `byte` is a lower-case ASCII letter. +// +// Lower-case ASCII letters all have the 0x20 bit set. +// (Two positions right of 0x80, the highest bit.) +// Unsetting that bit produces the same letter, in upper-case. +// +// Therefore: +fn branchless_to_ascii_upper_case(byte: u8) -> u8 { + byte & + !( + ( + byte.wrapping_add(0x1f) & + !byte.wrapping_add(0x05) & + 0x80 + ) >> 2 + ) +} + + +macro_rules! benches { + ($( fn $name: ident($arg: ident: &mut [u8]) $body: block )+) => { + benches!(mod short SHORT $($name $arg $body)+); + benches!(mod medium MEDIUM $($name $arg $body)+); + benches!(mod long LONG $($name $arg $body)+); + }; + + (mod $mod_name: ident $input: ident $($name: ident $arg: ident $body: block)+) => { + mod $mod_name { + use super::*; + + $( + #[bench] + fn $name(bencher: &mut Bencher) { + bencher.bytes = $input.len() as u64; + bencher.iter(|| { + let mut vec = $input.as_bytes().to_vec(); + { + let $arg = &mut vec[..]; + $body + } + vec + }) + } + )+ + } + } +} + +use test::black_box; +use test::Bencher; + +benches! { + fn bench00_alloc_only(_bytes: &mut [u8]) {} + + fn bench01_black_box_read_each_byte(bytes: &mut [u8]) { + for byte in bytes { + black_box(*byte); + } + } + + fn bench02_lookup(bytes: &mut [u8]) { + for byte in bytes { + *byte = ASCII_UPPERCASE_MAP[*byte as usize] + } + } + + fn bench03_branch_and_subtract(bytes: &mut [u8]) { + for byte in bytes { + *byte = if b'a' <= *byte && *byte <= b'z' { + *byte - b'a' + b'A' + } else { + *byte + } + } + } + + fn bench04_branch_and_mask(bytes: &mut [u8]) { + for byte in bytes { + *byte = if b'a' <= *byte && *byte <= b'z' { + *byte & !0x20 + } else { + *byte + } + } + } + + fn bench05_branchless(bytes: &mut [u8]) { + for byte in bytes { + *byte = branchless_to_ascii_upper_case(*byte) + } + } + + fn bench06_libcore(bytes: &mut [u8]) { + bytes.make_ascii_uppercase() + } +} + +macro_rules! repeat { + ($s: expr) => { concat!($s, $s, $s, $s, $s, $s, $s, $s, $s, $s) } +} + +const SHORT: &'static str = "Alice's"; +const MEDIUM: &'static str = "Alice's Adventures in Wonderland"; +const LONG: &'static str = repeat!(r#" + La Guida di Bragia, a Ballad Opera for the Marionette Theatre (around 1850) + Alice's Adventures in Wonderland (1865) + Phantasmagoria and Other Poems (1869) + Through the Looking-Glass, and What Alice Found There (includes "Jabberwocky" and "The Walrus and the Carpenter") (1871) + The Hunting of the Snark (1876) + Rhyme? And Reason? (1883) – shares some contents with the 1869 collection, including the long poem "Phantasmagoria" + A Tangled Tale (1885) + Sylvie and Bruno (1889) + Sylvie and Bruno Concluded (1893) + Pillow Problems (1893) + What the Tortoise Said to Achilles (1895) + Three Sunsets and Other Poems (1898) + The Manlet (1903)[106] +"#); + +const ASCII_UPPERCASE_MAP: [u8; 256] = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'', + b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', + b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', + b'8', b'9', b':', b';', b'<', b'=', b'>', b'?', + b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G', + b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', + b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', + b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_', + b'`', + + b'A', b'B', b'C', b'D', b'E', b'F', b'G', + b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', + b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', + b'X', b'Y', b'Z', + + b'{', b'|', b'}', b'~', 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index 48572af611a5b..b72d035b0ce94 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -5,6 +5,7 @@ extern crate core; extern crate test; mod any; +mod ascii_case; mod char; mod hash; mod iter; From ce933f77c865a15670855ac5941fe200752b739f Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 20:16:37 +0100 Subject: [PATCH 07/37] Make u8::to_ascii_lowercase and to_ascii_uppercase branchless --- src/libcore/benches/ascii_case.rs | 22 +----- src/libcore/num/mod.rs | 122 ++++++++++-------------------- 2 files changed, 43 insertions(+), 101 deletions(-) diff --git a/src/libcore/benches/ascii_case.rs b/src/libcore/benches/ascii_case.rs index 43242ca3f364e..1c9691d1ee173 100644 --- a/src/libcore/benches/ascii_case.rs +++ b/src/libcore/benches/ascii_case.rs @@ -1,24 +1,4 @@ -// Lower-case ASCII 'a' is the first byte that has its highest bit set after wrap-adding 0x1F: -// -// b'a' + 0x1F == 0x80 == 0b1000_0000 -// b'z' + 0x1F == 0x98 == 0b10011000 -// -// Lower-case ASCII 'z' is the last byte that has its highest bit unset after wrap-adding 0x05: -// -// b'a' + 0x05 == 0x66 == 0b0110_0110 -// b'z' + 0x05 == 0x7F == 0b0111_1111 -// -// … except for 0xFB to 0xFF, but those are in the range of bytes that have the highest bit -// unset again after adding 0x1F. -// -// So `(byte + 0x1f) & !(byte + 5)` has its highest bit set -// iff `byte` is a lower-case ASCII letter. -// -// Lower-case ASCII letters all have the 0x20 bit set. -// (Two positions right of 0x80, the highest bit.) -// Unsetting that bit produces the same letter, in upper-case. -// -// Therefore: +// See comments in `u8::to_ascii_uppercase` in `src/libcore/num/mod.rs`. fn branchless_to_ascii_upper_case(byte: u8) -> u8 { byte & !( diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index d93cfbc2a28ac..977e21e0dc89a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3794,7 +3794,39 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> u8 { - ASCII_UPPERCASE_MAP[*self as usize] + // See benchmarks in src/libcore/benches/ascii_case.rs + + // Lower-case ASCII 'a' is the first byte that has its highest bit set + // after wrap-adding 0x1F: + // + // b'a' + 0x1F == 0x80 == 0b1000_0000 + // b'z' + 0x1F == 0x98 == 0b10011000 + // + // Lower-case ASCII 'z' is the last byte that has its highest bit unset + // after wrap-adding 0x05: + // + // b'a' + 0x05 == 0x66 == 0b0110_0110 + // b'z' + 0x05 == 0x7F == 0b0111_1111 + // + // … except for 0xFB to 0xFF, but those are in the range of bytes + // that have the highest bit unset again after adding 0x1F. + // + // So `(byte + 0x1f) & !(byte + 5)` has its highest bit set + // iff `byte` is a lower-case ASCII letter. + // + // Lower-case ASCII letters all have the 0x20 bit set. + // (Two positions right of 0x80, the highest bit.) + // Unsetting that bit produces the same letter, in upper-case. + // + // Therefore: + *self & + !( + ( + self.wrapping_add(0x1f) & + !self.wrapping_add(0x05) & + 0x80 + ) >> 2 + ) } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -3816,7 +3848,15 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> u8 { - ASCII_LOWERCASE_MAP[*self as usize] + // See comments in to_ascii_uppercase above. + *self | + ( + ( + self.wrapping_add(0x3f) & + !self.wrapping_add(0x25) & + 0x80 + ) >> 2 + ) } /// Checks that two values are an ASCII case-insensitive match. @@ -4940,84 +4980,6 @@ impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" // Float -> Float impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -static ASCII_LOWERCASE_MAP: [u8; 256] = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'', - b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', - b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', - b'8', b'9', b':', b';', b'<', b'=', b'>', b'?', - b'@', - - b'a', b'b', b'c', b'd', b'e', b'f', b'g', - b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', - b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', - b'x', b'y', b'z', - - b'[', b'\\', b']', b'^', b'_', - b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g', - b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', - b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', - b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - -static ASCII_UPPERCASE_MAP: [u8; 256] = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'', - b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', - b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', - b'8', b'9', b':', b';', b'<', b'=', b'>', b'?', - b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G', - b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', - b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', - b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_', - b'`', - - b'A', b'B', b'C', b'D', b'E', b'F', b'G', - b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', - b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', - b'X', b'Y', b'Z', - - b'{', b'|', b'}', b'~', 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - enum AsciiCharacterClass { C, // control Cw, // control whitespace From fbe34cc521a5d0f04dd6afadb5b200f0338f41d9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 20:40:32 +0100 Subject: [PATCH 08/37] =?UTF-8?q?Add=20benchmark=20for=20not-quite-correct?= =?UTF-8?q?=20=E2=80=9Cfake=20SIMD=E2=80=9D=20make=5Fascii=5Fuppercase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libcore/benches/ascii_case.rs | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/libcore/benches/ascii_case.rs b/src/libcore/benches/ascii_case.rs index 1c9691d1ee173..df82a8cb1d537 100644 --- a/src/libcore/benches/ascii_case.rs +++ b/src/libcore/benches/ascii_case.rs @@ -87,6 +87,52 @@ benches! { fn bench06_libcore(bytes: &mut [u8]) { bytes.make_ascii_uppercase() } + + fn bench07_fake_simd_u32(bytes: &mut [u8]) { + let (before, aligned, after) = unsafe { + bytes.align_to_mut::() + }; + for byte in before { + *byte = branchless_to_ascii_upper_case(*byte) + } + for word in aligned { + // FIXME: this is incorrect for some byte values: + // addition within a byte can carry/overflow into the next byte. + // Test case: b"\xFFz " + *word &= !( + ( + word.wrapping_add(0x1f1f1f1f) & + !word.wrapping_add(0x05050505) & + 0x80808080 + ) >> 2 + ) + } + for byte in after { + *byte = branchless_to_ascii_upper_case(*byte) + } + } + + fn bench08_fake_simd_u64(bytes: &mut [u8]) { + let (before, aligned, after) = unsafe { + bytes.align_to_mut::() + }; + for byte in before { + *byte = branchless_to_ascii_upper_case(*byte) + } + for word in aligned { + // FIXME: like above, this is incorrect for some byte values. + *word &= !( + ( + word.wrapping_add(0x1f1f1f1f_1f1f1f1f) & + !word.wrapping_add(0x05050505_05050505) & + 0x80808080_80808080 + ) >> 2 + ) + } + for byte in after { + *byte = branchless_to_ascii_upper_case(*byte) + } + } } macro_rules! repeat { From e3fb6f89fef4fea94deeac572b0373843560c2d6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 21:28:33 +0100 Subject: [PATCH 09/37] Tidy --- src/libcore/benches/ascii_case.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/benches/ascii_case.rs b/src/libcore/benches/ascii_case.rs index df82a8cb1d537..dcc87cc45b1e3 100644 --- a/src/libcore/benches/ascii_case.rs +++ b/src/libcore/benches/ascii_case.rs @@ -145,9 +145,11 @@ const LONG: &'static str = repeat!(r#" La Guida di Bragia, a Ballad Opera for the Marionette Theatre (around 1850) Alice's Adventures in Wonderland (1865) Phantasmagoria and Other Poems (1869) - Through the Looking-Glass, and What Alice Found There (includes "Jabberwocky" and "The Walrus and the Carpenter") (1871) + Through the Looking-Glass, and What Alice Found There + (includes "Jabberwocky" and "The Walrus and the Carpenter") (1871) The Hunting of the Snark (1876) - Rhyme? And Reason? (1883) – shares some contents with the 1869 collection, including the long poem "Phantasmagoria" + Rhyme? And Reason? (1883) – shares some contents with the 1869 collection, + including the long poem "Phantasmagoria" A Tangled Tale (1885) Sylvie and Bruno (1889) Sylvie and Bruno Concluded (1893) From 525a043c6bc8a220b7dbdde3eb10bb79f8e99506 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 23:32:36 +0100 Subject: [PATCH 10/37] Rename src/libcore/benches/ascii_case.rs to ascii.rs --- src/libcore/benches/{ascii_case.rs => ascii.rs} | 6 ++++++ src/libcore/benches/lib.rs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) rename src/libcore/benches/{ascii_case.rs => ascii.rs} (97%) diff --git a/src/libcore/benches/ascii_case.rs b/src/libcore/benches/ascii.rs similarity index 97% rename from src/libcore/benches/ascii_case.rs rename to src/libcore/benches/ascii.rs index dcc87cc45b1e3..2714a8a5c278e 100644 --- a/src/libcore/benches/ascii_case.rs +++ b/src/libcore/benches/ascii.rs @@ -84,6 +84,12 @@ benches! { } } + fn bench05_multiply_by_bool(bytes: &mut [u8]) { + for byte in bytes { + *byte &= !(0x20 * (b'a' <= *byte && *byte <= b'z') as u8) + } + } + fn bench06_libcore(bytes: &mut [u8]) { bytes.make_ascii_uppercase() } diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index b72d035b0ce94..707cdd5f450ea 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -5,7 +5,7 @@ extern crate core; extern crate test; mod any; -mod ascii_case; +mod ascii; mod char; mod hash; mod iter; From 6d3840b23a185d057cc9792a2516e6a71887f277 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 23:56:50 +0100 Subject: [PATCH 11/37] Add benchmarks for `u8::is_ascii*` --- src/libcore/benches/ascii.rs | 49 +++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index 2714a8a5c278e..e20b1b9bf3136 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -12,7 +12,14 @@ fn branchless_to_ascii_upper_case(byte: u8) -> u8 { macro_rules! benches { - ($( fn $name: ident($arg: ident: &mut [u8]) $body: block )+) => { + ($( fn $name: ident($arg: ident: &mut [u8]) $body: block )+ @iter $( $is_: ident, )+) => { + benches! {@ + $( fn $name($arg: &mut [u8]) $body )+ + $( fn $is_(bytes: &mut [u8]) { bytes.iter().all(u8::$is_) } )+ + } + }; + + (@$( fn $name: ident($arg: ident: &mut [u8]) $body: block )+) => { benches!(mod short SHORT $($name $arg $body)+); benches!(mod medium MEDIUM $($name $arg $body)+); benches!(mod long LONG $($name $arg $body)+); @@ -30,7 +37,7 @@ macro_rules! benches { let mut vec = $input.as_bytes().to_vec(); { let $arg = &mut vec[..]; - $body + black_box($body); } vec }) @@ -44,21 +51,21 @@ use test::black_box; use test::Bencher; benches! { - fn bench00_alloc_only(_bytes: &mut [u8]) {} + fn case00_alloc_only(_bytes: &mut [u8]) {} - fn bench01_black_box_read_each_byte(bytes: &mut [u8]) { + fn case01_black_box_read_each_byte(bytes: &mut [u8]) { for byte in bytes { black_box(*byte); } } - fn bench02_lookup(bytes: &mut [u8]) { + fn case02_lookup(bytes: &mut [u8]) { for byte in bytes { *byte = ASCII_UPPERCASE_MAP[*byte as usize] } } - fn bench03_branch_and_subtract(bytes: &mut [u8]) { + fn case03_branch_and_subtract(bytes: &mut [u8]) { for byte in bytes { *byte = if b'a' <= *byte && *byte <= b'z' { *byte - b'a' + b'A' @@ -68,7 +75,7 @@ benches! { } } - fn bench04_branch_and_mask(bytes: &mut [u8]) { + fn case04_branch_and_mask(bytes: &mut [u8]) { for byte in bytes { *byte = if b'a' <= *byte && *byte <= b'z' { *byte & !0x20 @@ -78,23 +85,17 @@ benches! { } } - fn bench05_branchless(bytes: &mut [u8]) { + fn case05_branchless(bytes: &mut [u8]) { for byte in bytes { *byte = branchless_to_ascii_upper_case(*byte) } } - fn bench05_multiply_by_bool(bytes: &mut [u8]) { - for byte in bytes { - *byte &= !(0x20 * (b'a' <= *byte && *byte <= b'z') as u8) - } - } - - fn bench06_libcore(bytes: &mut [u8]) { + fn case06_libcore(bytes: &mut [u8]) { bytes.make_ascii_uppercase() } - fn bench07_fake_simd_u32(bytes: &mut [u8]) { + fn case07_fake_simd_u32(bytes: &mut [u8]) { let (before, aligned, after) = unsafe { bytes.align_to_mut::() }; @@ -118,7 +119,7 @@ benches! { } } - fn bench08_fake_simd_u64(bytes: &mut [u8]) { + fn case08_fake_simd_u64(bytes: &mut [u8]) { let (before, aligned, after) = unsafe { bytes.align_to_mut::() }; @@ -139,6 +140,20 @@ benches! { *byte = branchless_to_ascii_upper_case(*byte) } } + + @iter + + is_ascii, + is_ascii_alphabetic, + is_ascii_uppercase, + is_ascii_lowercase, + is_ascii_alphanumeric, + is_ascii_digit, + is_ascii_hexdigit, + is_ascii_punctuation, + is_ascii_graphic, + is_ascii_whitespace, + is_ascii_control, } macro_rules! repeat { From b4faa9b45635ae5185d562701d7429e5fbb08c8b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Mar 2019 23:57:09 +0100 Subject: [PATCH 12/37] Remove ASCII_CHARACTER_CLASS table, use `match` with range patterns instead. --- src/libcore/num/mod.rs | 75 +++++++++++------------------------------- 1 file changed, 20 insertions(+), 55 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 977e21e0dc89a..64469a4b7e43c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3958,9 +3958,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_alphabetic(&self) -> bool { - if *self >= 0x80 { return false; } - match ASCII_CHARACTER_CLASS[*self as usize] { - L | Lx | U | Ux => true, + match *self { + b'A'...b'Z' | b'a'...b'z' => true, _ => false } } @@ -3994,9 +3993,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_uppercase(&self) -> bool { - if *self >= 0x80 { return false } - match ASCII_CHARACTER_CLASS[*self as usize] { - U | Ux => true, + match *self { + b'A'...b'Z' => true, _ => false } } @@ -4030,9 +4028,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_lowercase(&self) -> bool { - if *self >= 0x80 { return false } - match ASCII_CHARACTER_CLASS[*self as usize] { - L | Lx => true, + match *self { + b'a'...b'z' => true, _ => false } } @@ -4069,9 +4066,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_alphanumeric(&self) -> bool { - if *self >= 0x80 { return false } - match ASCII_CHARACTER_CLASS[*self as usize] { - D | L | Lx | U | Ux => true, + match *self { + b'0'...b'9' | b'A'...b'Z' | b'a'...b'z' => true, _ => false } } @@ -4105,9 +4101,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_digit(&self) -> bool { - if *self >= 0x80 { return false } - match ASCII_CHARACTER_CLASS[*self as usize] { - D => true, + match *self { + b'0'...b'9' => true, _ => false } } @@ -4144,9 +4139,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_hexdigit(&self) -> bool { - if *self >= 0x80 { return false } - match ASCII_CHARACTER_CLASS[*self as usize] { - D | Lx | Ux => true, + match *self { + b'0'...b'9' | b'A'...b'F' | b'a'...b'f' => true, _ => false } } @@ -4184,9 +4178,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_punctuation(&self) -> bool { - if *self >= 0x80 { return false } - match ASCII_CHARACTER_CLASS[*self as usize] { - P => true, + match *self { + b'!'...b'/' | b':'...b'@' | b'['...b'`' | b'{'...b'~' => true, _ => false } } @@ -4220,9 +4213,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_graphic(&self) -> bool { - if *self >= 0x80 { return false; } - match ASCII_CHARACTER_CLASS[*self as usize] { - Ux | U | Lx | L | D | P => true, + match *self { + b'!'...b'~' => true, _ => false } } @@ -4273,9 +4265,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_whitespace(&self) -> bool { - if *self >= 0x80 { return false; } - match ASCII_CHARACTER_CLASS[*self as usize] { - Cw | W => true, + match *self { + b'\t' | b'\n' | b'\x0C' | b'\r' | b' ' => true, _ => false } } @@ -4311,9 +4302,8 @@ impl u8 { #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[inline] pub fn is_ascii_control(&self) -> bool { - if *self >= 0x80 { return false; } - match ASCII_CHARACTER_CLASS[*self as usize] { - C | Cw => true, + match *self { + b'\0'...b'\x1F' | b'\x7F' => true, _ => false } } @@ -4979,28 +4969,3 @@ impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" // Float -> Float impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } - -enum AsciiCharacterClass { - C, // control - Cw, // control whitespace - W, // whitespace - D, // digit - L, // lowercase - Lx, // lowercase hex digit - U, // uppercase - Ux, // uppercase hex digit - P, // punctuation -} -use self::AsciiCharacterClass::*; - -static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [ -// _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f - C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_ - C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_ - W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_ - D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_ - P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_ - U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_ - P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_ - L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_ -]; From 4a3241a815e951dfa87e9be7133e8265bc945e57 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 19 Mar 2019 00:34:27 +0100 Subject: [PATCH 13/37] Benchmark more possibles impls of [u8]::make_ascii_uppercase --- src/libcore/benches/ascii.rs | 84 +++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index e20b1b9bf3136..ce36027394a48 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -59,7 +59,7 @@ benches! { } } - fn case02_lookup(bytes: &mut [u8]) { + fn case02_lookup_table(bytes: &mut [u8]) { for byte in bytes { *byte = ASCII_UPPERCASE_MAP[*byte as usize] } @@ -141,6 +141,55 @@ benches! { } } + fn case09_mask_mult_bool_branchy_lookup_table(bytes: &mut [u8]) { + fn is_ascii_lowercase(b: u8) -> bool { + if b >= 0x80 { return false } + match ASCII_CHARACTER_CLASS[b as usize] { + L | Lx => true, + _ => false, + } + } + for byte in bytes { + *byte &= !(0x20 * (is_ascii_lowercase(*byte) as u8)) + } + } + + fn case10_mask_mult_bool_lookup_table(bytes: &mut [u8]) { + fn is_ascii_lowercase(b: u8) -> bool { + match ASCII_CHARACTER_CLASS[b as usize] { + L | Lx => true, + _ => false + } + } + for byte in bytes { + *byte &= !(0x20 * (is_ascii_lowercase(*byte) as u8)) + } + } + + fn case11_mask_mult_bool_match_range(bytes: &mut [u8]) { + fn is_ascii_lowercase(b: u8) -> bool { + match b { + b'a'...b'z' => true, + _ => false + } + } + for byte in bytes { + *byte &= !(0x20 * (is_ascii_lowercase(*byte) as u8)) + } + } + + fn case12_mask_shifted_bool_match_range(bytes: &mut [u8]) { + fn is_ascii_lowercase(b: u8) -> bool { + match b { + b'a'...b'z' => true, + _ => false + } + } + for byte in bytes { + *byte &= !((is_ascii_lowercase(*byte) as u8) << 5) + } + } + @iter is_ascii, @@ -219,3 +268,36 @@ const ASCII_UPPERCASE_MAP: [u8; 256] = [ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, ]; +enum AsciiCharacterClass { + C, // control + Cw, // control whitespace + W, // whitespace + D, // digit + L, // lowercase + Lx, // lowercase hex digit + U, // uppercase + Ux, // uppercase hex digit + P, // punctuation + N, // Non-ASCII +} +use self::AsciiCharacterClass::*; + +static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [ +// _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f + C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_ + C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_ + W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_ + D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_ + P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_ + U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_ + P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_ + L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_ + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, +]; From 0ad91f73d92c3b8d3978f8f54c04b8efe3d2e673 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 19 Mar 2019 00:50:26 +0100 Subject: [PATCH 14/37] Simplify u8::to_ascii_{upp,low}ercase while keeping it fast --- src/libcore/benches/ascii.rs | 24 ++++++++++++++++++- src/libcore/num/mod.rs | 46 ++++-------------------------------- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index ce36027394a48..89e67cca4b754 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -1,4 +1,26 @@ -// See comments in `u8::to_ascii_uppercase` in `src/libcore/num/mod.rs`. +// Lower-case ASCII 'a' is the first byte that has its highest bit set +// after wrap-adding 0x1F: +// +// b'a' + 0x1F == 0x80 == 0b1000_0000 +// b'z' + 0x1F == 0x98 == 0b10011000 +// +// Lower-case ASCII 'z' is the last byte that has its highest bit unset +// after wrap-adding 0x05: +// +// b'a' + 0x05 == 0x66 == 0b0110_0110 +// b'z' + 0x05 == 0x7F == 0b0111_1111 +// +// … except for 0xFB to 0xFF, but those are in the range of bytes +// that have the highest bit unset again after adding 0x1F. +// +// So `(byte + 0x1f) & !(byte + 5)` has its highest bit set +// iff `byte` is a lower-case ASCII letter. +// +// Lower-case ASCII letters all have the 0x20 bit set. +// (Two positions right of 0x80, the highest bit.) +// Unsetting that bit produces the same letter, in upper-case. +// +// Therefore: fn branchless_to_ascii_upper_case(byte: u8) -> u8 { byte & !( diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 64469a4b7e43c..3fcae6b94b06d 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3794,39 +3794,8 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> u8 { - // See benchmarks in src/libcore/benches/ascii_case.rs - - // Lower-case ASCII 'a' is the first byte that has its highest bit set - // after wrap-adding 0x1F: - // - // b'a' + 0x1F == 0x80 == 0b1000_0000 - // b'z' + 0x1F == 0x98 == 0b10011000 - // - // Lower-case ASCII 'z' is the last byte that has its highest bit unset - // after wrap-adding 0x05: - // - // b'a' + 0x05 == 0x66 == 0b0110_0110 - // b'z' + 0x05 == 0x7F == 0b0111_1111 - // - // … except for 0xFB to 0xFF, but those are in the range of bytes - // that have the highest bit unset again after adding 0x1F. - // - // So `(byte + 0x1f) & !(byte + 5)` has its highest bit set - // iff `byte` is a lower-case ASCII letter. - // - // Lower-case ASCII letters all have the 0x20 bit set. - // (Two positions right of 0x80, the highest bit.) - // Unsetting that bit produces the same letter, in upper-case. - // - // Therefore: - *self & - !( - ( - self.wrapping_add(0x1f) & - !self.wrapping_add(0x05) & - 0x80 - ) >> 2 - ) + // Unset the fith bit if this is a lowercase letter + *self & !((self.is_ascii_lowercase() as u8) << 5) } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -3848,15 +3817,8 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> u8 { - // See comments in to_ascii_uppercase above. - *self | - ( - ( - self.wrapping_add(0x3f) & - !self.wrapping_add(0x25) & - 0x80 - ) >> 2 - ) + // Set the fith bit if this is an uppercase letter + *self | ((self.is_ascii_uppercase() as u8) << 5) } /// Checks that two values are an ASCII case-insensitive match. From c1ec29ace000ce4c733cde6948c87f9bc2370691 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 19 Mar 2019 08:32:15 +0100 Subject: [PATCH 15/37] ASCII uppercase: add "subtract shifted bool" benchmark --- src/libcore/benches/ascii.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index 89e67cca4b754..968d28a995897 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -212,6 +212,18 @@ benches! { } } + fn case13_subtract_shifted_bool_match_range(bytes: &mut [u8]) { + fn is_ascii_lowercase(b: u8) -> bool { + match b { + b'a'...b'z' => true, + _ => false + } + } + for byte in bytes { + *byte -= (is_ascii_lowercase(*byte) as u8) << 5 + } + } + @iter is_ascii, From 7fad370fe9dc000f6f6f497a1939de6196e2c4fc Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 19 Mar 2019 13:41:59 +0100 Subject: [PATCH 16/37] ASCII uppercase: add "subtract multiplied bool" benchmark --- src/libcore/benches/ascii.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index 968d28a995897..635537e312158 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -224,6 +224,18 @@ benches! { } } + fn case14_subtract_multiplied_bool_match_range(bytes: &mut [u8]) { + fn is_ascii_lowercase(b: u8) -> bool { + match b { + b'a'...b'z' => true, + _ => false + } + } + for byte in bytes { + *byte -= (b'a' - b'A') * is_ascii_lowercase(*byte) as u8 + } + } + @iter is_ascii, From b34a71b7daf0f770cd5e7f9c36be960e32d2b167 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Fri, 22 Mar 2019 14:56:08 -0400 Subject: [PATCH 17/37] add suggestions to trim_{left,right} deprecations --- src/libcore/str/mod.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 528281d317be3..f54d7badc3ae0 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -3601,7 +3601,11 @@ impl str { /// assert!(Some('ע') == s.trim_left().chars().next()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(reason = "superseded by `trim_start`", since = "1.33.0")] + #[rustc_deprecated( + since = "1.33.0", + reason = "superseded by `trim_start`", + suggestion = "trim_start", + )] pub fn trim_left(&self) -> &str { self.trim_start() } @@ -3638,7 +3642,11 @@ impl str { /// assert!(Some('ת') == s.trim_right().chars().rev().next()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(reason = "superseded by `trim_end`", since = "1.33.0")] + #[rustc_deprecated( + since = "1.33.0", + reason = "superseded by `trim_end`", + suggestion = "trim_end", + )] pub fn trim_right(&self) -> &str { self.trim_end() } @@ -3802,7 +3810,11 @@ impl str { /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(reason = "superseded by `trim_start_matches`", since = "1.33.0")] + #[rustc_deprecated( + since = "1.33.0", + reason = "superseded by `trim_start_matches`", + suggestion = "trim_start_matches", + )] pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { self.trim_start_matches(pat) } @@ -3840,7 +3852,11 @@ impl str { /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(reason = "superseded by `trim_end_matches`", since = "1.33.0")] + #[rustc_deprecated( + since = "1.33.0", + reason = "superseded by `trim_end_matches`", + suggestion = "trim_end_matches", + )] pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str where P::Searcher: ReverseSearcher<'a> { From ac3290e8d949448193014c85096f8772db331d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 17 Mar 2019 22:42:51 -0700 Subject: [PATCH 18/37] Add suggestion to use `&*var` when `&str: From` is expected --- .../src/language-features/on-unimplemented.md | 12 ++++++++++++ src/libcore/convert.rs | 6 ++++++ src/test/ui/suggestions/into-str.rs | 6 ++++++ src/test/ui/suggestions/into-str.stderr | 17 +++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 src/test/ui/suggestions/into-str.rs create mode 100644 src/test/ui/suggestions/into-str.stderr diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md index f787f629756f3..b156038fba06d 100644 --- a/src/doc/unstable-book/src/language-features/on-unimplemented.md +++ b/src/doc/unstable-book/src/language-features/on-unimplemented.md @@ -138,3 +138,15 @@ error[E0277]: `&str` is not an iterator = help: the trait `std::iter::Iterator` is not implemented for `&str` = note: required by `std::iter::IntoIterator::into_iter` ``` + +If you need to filter on multiple attributes, you can use `all` in the following way: + +```rust,compile_fail +#[rustc_on_unimplemented( + on( + all(_Self="&str", T="std::string::String"), + note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" + ) +)] +pub trait From: Sized { /* ... */ } +``` \ No newline at end of file diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 774d648558b48..cb574a53dbccb 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -352,6 +352,12 @@ pub trait Into: Sized { /// [`from`]: trait.From.html#tymethod.from /// [book]: ../../book/ch09-00-error-handling.html #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + on( + all(_Self="&str", T="std::string::String"), + note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" + ) +)] pub trait From: Sized { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/suggestions/into-str.rs b/src/test/ui/suggestions/into-str.rs new file mode 100644 index 0000000000000..9793ee801d185 --- /dev/null +++ b/src/test/ui/suggestions/into-str.rs @@ -0,0 +1,6 @@ +fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + +fn main() { + foo(String::new()); + //~^ ERROR the trait bound `&str: std::convert::From` is not satisfied +} diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr new file mode 100644 index 0000000000000..f341d36370213 --- /dev/null +++ b/src/test/ui/suggestions/into-str.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `&str: std::convert::From` is not satisfied + --> $DIR/into-str.rs:4:5 + | +LL | foo(String::new()); + | ^^^ the trait `std::convert::From` is not implemented for `&str` + | + = note: you can coerce a `std::string::String` into a `&str` by writing `&*variable` + = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` +note: required by `foo` + --> $DIR/into-str.rs:1:1 + | +LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 2f7b32091ecdc86520d75aa8fe6bcffb5849732d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 18 Mar 2019 11:06:48 -0700 Subject: [PATCH 19/37] extend on-unimplemented docs --- .../unstable-book/src/language-features/on-unimplemented.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md index b156038fba06d..a770ab65c26f8 100644 --- a/src/doc/unstable-book/src/language-features/on-unimplemented.md +++ b/src/doc/unstable-book/src/language-features/on-unimplemented.md @@ -139,7 +139,8 @@ error[E0277]: `&str` is not an iterator = note: required by `std::iter::IntoIterator::into_iter` ``` -If you need to filter on multiple attributes, you can use `all` in the following way: +If you need to filter on multiple attributes, you can use `all`, `any` or +`not` in the following way: ```rust,compile_fail #[rustc_on_unimplemented( @@ -149,4 +150,4 @@ If you need to filter on multiple attributes, you can use `all` in the following ) )] pub trait From: Sized { /* ... */ } -``` \ No newline at end of file +``` From e929d19edc99e5eb7af319709247470cff99719b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 22 Mar 2019 20:38:09 -0700 Subject: [PATCH 20/37] review comments --- src/libcore/convert.rs | 2 +- src/test/ui/suggestions/into-str.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index cb574a53dbccb..d36de3bbe8691 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -355,7 +355,7 @@ pub trait Into: Sized { #[rustc_on_unimplemented( on( all(_Self="&str", T="std::string::String"), - note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" + note="to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", ) )] pub trait From: Sized { diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index f341d36370213..3e28700ce9552 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&str: std::convert::From` is LL | foo(String::new()); | ^^^ the trait `std::convert::From` is not implemented for `&str` | - = note: you can coerce a `std::string::String` into a `&str` by writing `&*variable` + = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` note: required by `foo` --> $DIR/into-str.rs:1:1 From 4b382946e4fffb0f82e821ae4f8239a439b35207 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Jan 2019 04:52:59 +0300 Subject: [PATCH 21/37] syntax: Remove warning for unnecessary path disambiguators --- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/parse/parser.rs | 31 ++++++---------- .../packed/packed-struct-generic-size.rs | 12 +++---- .../packed/packed-struct-generic-size.stderr | 36 ------------------- src/test/ui/issues/issue-36116.rs | 6 ++-- src/test/ui/issues/issue-36116.stderr | 12 ------- 6 files changed, 20 insertions(+), 79 deletions(-) delete mode 100644 src/test/run-pass/packed/packed-struct-generic-size.stderr delete mode 100644 src/test/ui/issues/issue-36116.stderr diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 1a419e7fadaa0..ab5823eaca52a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -929,7 +929,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { p.fatal(&format!("expected ident, found {}", &token_str)).emit(); FatalError.raise() } - "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))), + "path" => token::NtPath(panictry!(p.parse_path(PathStyle::Type))), "meta" => token::NtMeta(panictry!(p.parse_meta_item())), "vis" => token::NtVis(panictry!(p.parse_visibility(true))), "lifetime" => if p.check_lifetime() { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6ff06aa4b31d3..c3e1aa7ae117f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1903,7 +1903,7 @@ impl<'a> Parser<'a> { self.expect(&token::ModSep)?; let mut path = ast::Path { segments: Vec::new(), span: syntax_pos::DUMMY_SP }; - self.parse_path_segments(&mut path.segments, T::PATH_STYLE, true)?; + self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?; path.span = ty_span.to(self.prev_span); let ty_str = self.sess.source_map().span_to_snippet(ty_span) @@ -2294,7 +2294,7 @@ impl<'a> Parser<'a> { self.expect(&token::ModSep)?; let qself = QSelf { ty, path_span, position: path.segments.len() }; - self.parse_path_segments(&mut path.segments, style, true)?; + self.parse_path_segments(&mut path.segments, style)?; Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) })) } @@ -2310,11 +2310,6 @@ impl<'a> Parser<'a> { /// `Fn(Args)` (without disambiguator) /// `Fn::(Args)` (with disambiguator) pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - self.parse_path_common(style, true) - } - - crate fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool) - -> PResult<'a, ast::Path> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { @@ -2329,7 +2324,7 @@ impl<'a> Parser<'a> { if self.eat(&token::ModSep) { segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } - self.parse_path_segments(&mut segments, style, enable_warning)?; + self.parse_path_segments(&mut segments, style)?; Ok(ast::Path { segments, span: lo.to(self.prev_span) }) } @@ -2357,11 +2352,10 @@ impl<'a> Parser<'a> { fn parse_path_segments(&mut self, segments: &mut Vec, - style: PathStyle, - enable_warning: bool) + style: PathStyle) -> PResult<'a, ()> { loop { - let segment = self.parse_path_segment(style, enable_warning)?; + let segment = self.parse_path_segment(style)?; if style == PathStyle::Expr { // In order to check for trailing angle brackets, we must have finished // recursing (`parse_path_segment` can indirectly call this function), @@ -2389,8 +2383,7 @@ impl<'a> Parser<'a> { } } - fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool) - -> PResult<'a, PathSegment> { + fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { let ident = self.parse_path_segment_ident()?; let is_args_start = |token: &token::Token| match *token { @@ -2407,13 +2400,6 @@ impl<'a> Parser<'a> { Ok(if style == PathStyle::Type && check_args_start(self) || style != PathStyle::Mod && self.check(&token::ModSep) && self.look_ahead(1, |t| is_args_start(t)) { - // Generic arguments are found - `<`, `(`, `::<` or `::(`. - if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning { - self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator") - .span_label(self.prev_span, "try removing `::`").emit(); - } - let lo = self.span; - // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If // it isn't, then we reset the unmatched angle bracket count as we're about to start // parsing a new path. @@ -2422,6 +2408,9 @@ impl<'a> Parser<'a> { self.max_angle_bracket_count = 0; } + // Generic arguments are found - `<`, `(`, `::<` or `::(`. + self.eat(&token::ModSep); + let lo = self.span; let args = if self.eat_lt() { // `<'a, T, A = U>` let (args, bindings) = @@ -3043,7 +3032,7 @@ impl<'a> Parser<'a> { // Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - let segment = self.parse_path_segment(PathStyle::Expr, true)?; + let segment = self.parse_path_segment(PathStyle::Expr)?; self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); Ok(match self.token { diff --git a/src/test/run-pass/packed/packed-struct-generic-size.rs b/src/test/run-pass/packed/packed-struct-generic-size.rs index 08d4674d2a88a..7c93e46c30c23 100644 --- a/src/test/run-pass/packed/packed-struct-generic-size.rs +++ b/src/test/run-pass/packed/packed-struct-generic-size.rs @@ -33,12 +33,12 @@ macro_rules! check { } pub fn main() { - check!(P1::, 1, 3); - check!(P1::, 1, 11); + check!(P1, 1, 3); + check!(P1, 1, 11); - check!(P2::, 1, 3); - check!(P2::, 2, 12); + check!(P2, 1, 3); + check!(P2, 2, 12); - check!(P4C::, 1, 3); - check!(P4C::, 4, 12); + check!(P4C, 1, 3); + check!(P4C, 4, 12); } diff --git a/src/test/run-pass/packed/packed-struct-generic-size.stderr b/src/test/run-pass/packed/packed-struct-generic-size.stderr deleted file mode 100644 index 1af476c156866..0000000000000 --- a/src/test/run-pass/packed/packed-struct-generic-size.stderr +++ /dev/null @@ -1,36 +0,0 @@ -warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:36:14 - | -LL | check!(P1::, 1, 3); - | ^^ try removing `::` - -warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:37:14 - | -LL | check!(P1::, 1, 11); - | ^^ try removing `::` - -warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:39:14 - | -LL | check!(P2::, 1, 3); - | ^^ try removing `::` - -warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:40:14 - | -LL | check!(P2::, 2, 12); - | ^^ try removing `::` - -warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:42:15 - | -LL | check!(P4C::, 1, 3); - | ^^ try removing `::` - -warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:43:15 - | -LL | check!(P4C::, 4, 12); - | ^^ try removing `::` - diff --git a/src/test/ui/issues/issue-36116.rs b/src/test/ui/issues/issue-36116.rs index f4fe96cf75b55..b4bfba4d6e5d7 100644 --- a/src/test/ui/issues/issue-36116.rs +++ b/src/test/ui/issues/issue-36116.rs @@ -17,10 +17,10 @@ struct Foo { struct S(T); fn f() { - let f = Some(Foo { _a: 42 }).map(|a| a as Foo::); //~ WARN unnecessary path disambiguator - let g: Foo:: = Foo { _a: 42 }; //~ WARN unnecessary path disambiguator + let f = Some(Foo { _a: 42 }).map(|a| a as Foo::); + let g: Foo:: = Foo { _a: 42 }; - m!(S::); // OK, no warning + m!(S::); } diff --git a/src/test/ui/issues/issue-36116.stderr b/src/test/ui/issues/issue-36116.stderr deleted file mode 100644 index 5236db29ae4af..0000000000000 --- a/src/test/ui/issues/issue-36116.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: unnecessary path disambiguator - --> $DIR/issue-36116.rs:20:50 - | -LL | let f = Some(Foo { _a: 42 }).map(|a| a as Foo::); - | ^^ try removing `::` - -warning: unnecessary path disambiguator - --> $DIR/issue-36116.rs:21:15 - | -LL | let g: Foo:: = Foo { _a: 42 }; - | ^^ try removing `::` - From 7e156c2066bd9bf3a3d076ed32dd0d7b217c5857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 11 Jun 2018 08:48:15 +0200 Subject: [PATCH 22/37] Make some lints incremental --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/hir/map/mod.rs | 8 +-- src/librustc/lint/context.rs | 80 ++++++++++++++++++++++++++---- src/librustc/lint/mod.rs | 1 + src/librustc/ty/query/mod.rs | 2 + src/librustc/ty/query/plumbing.rs | 1 + src/librustc_interface/passes.rs | 2 +- src/librustc_lint/lib.rs | 53 +++++++++++++++++--- src/librustc_privacy/lib.rs | 3 +- 9 files changed, 127 insertions(+), 24 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 43e865ad08941..792b0ce714634 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -474,6 +474,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] UnsafetyCheckResult(DefId), [] UnsafeDeriveOnReprPacked(DefId), + [] LintMod(DefId), [] CheckModAttrs(DefId), [] CheckModLoops(DefId), [] CheckModUnstableApiUsage(DefId), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d810a9310c55f..56c3c71339f14 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -580,17 +580,17 @@ impl<'hir> Map<'hir> { &self.forest.krate.attrs } - pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId) - { + pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) { let node_id = self.as_local_node_id(module).unwrap(); + let hir_id = self.node_to_hir_id(node_id); self.read(node_id); match self.find_entry(node_id).unwrap().node { Node::Item(&Item { span, node: ItemKind::Mod(ref m), .. - }) => (m, span, node_id), - Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id), + }) => (m, span, hir_id), + Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id), _ => panic!("not a module") } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 94f1d9c271007..6df3409d080e7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -27,6 +27,7 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use crate::session::{config, early_error, Session}; use crate::ty::{self, TyCtxt, Ty}; use crate::ty::layout::{LayoutError, LayoutOf, TyLayout}; +use crate::ty::query::Providers; use crate::util::nodemap::FxHashMap; use crate::util::common::time; @@ -36,7 +37,7 @@ use syntax::edition; use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}}; use errors::DiagnosticBuilder; use crate::hir; -use crate::hir::def_id::LOCAL_CRATE; +use crate::hir::def_id::{DefId, LOCAL_CRATE}; use crate::hir::intravisit as hir_visit; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; @@ -55,6 +56,7 @@ pub struct LintStore { pre_expansion_passes: Option>, early_passes: Option>, late_passes: Option>, + late_module_passes: Option>, /// Lints indexed by name. by_name: FxHashMap, @@ -150,6 +152,7 @@ impl LintStore { pre_expansion_passes: Some(vec![]), early_passes: Some(vec![]), late_passes: Some(vec![]), + late_module_passes: Some(vec![]), by_name: Default::default(), future_incompatible: Default::default(), lint_groups: Default::default(), @@ -199,9 +202,14 @@ impl LintStore { pub fn register_late_pass(&mut self, sess: Option<&Session>, from_plugin: bool, + per_module: bool, pass: LateLintPassObject) { self.push_pass(sess, from_plugin, &pass); - self.late_passes.as_mut().unwrap().push(pass); + if per_module { + self.late_module_passes.as_mut().unwrap().push(pass); + } else { + self.late_passes.as_mut().unwrap().push(pass); + } } // Helper method for register_early/late_pass @@ -508,6 +516,7 @@ pub struct LateContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Side-tables for the body we are in. + // FIXME: Make this lazy to avoid running the TypeckTables query? pub tables: &'a ty::TypeckTables<'tcx>, /// Parameter environment for the item we are in. @@ -523,6 +532,9 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Generic type parameters in scope for the item we are in. pub generics: Option<&'tcx hir::Generics>, + + /// We are only looking at one module + only_module: bool, } /// Context for lint checking of the AST, after expansion, before lowering to @@ -803,6 +815,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { pub fn current_lint_root(&self) -> hir::HirId { self.last_node_with_lint_attrs } + + fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) { + run_lints!(self, check_mod, m, s, n); + hir_visit::walk_mod(self, m, n); + run_lints!(self, check_mod_post, m, s, n); + } } impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> { @@ -934,9 +952,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) { - run_lints!(self, check_mod, m, s, n); - hir_visit::walk_mod(self, m, n); - run_lints!(self, check_mod_post, m, s, n); + if !self.only_module { + self.process_mod(m, s, n); + } } fn visit_local(&mut self, l: &'tcx hir::Local) { @@ -1203,11 +1221,43 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } } +pub fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); -/// Performs lint checking on a crate. -/// -/// Consumes the `lint_store` field of the `Session`. -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let store = &tcx.sess.lint_store; + let passes = store.borrow_mut().late_module_passes.take(); + + let mut cx = LateContext { + tcx, + tables: &ty::TypeckTables::empty(None), + param_env: ty::ParamEnv::empty(), + access_levels, + lint_sess: LintSession { + lints: store.borrow(), + passes, + }, + last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(), + generics: None, + only_module: true, + }; + + let (module, span, hir_id) = tcx.hir().get_module(module_def_id); + cx.process_mod(module, span, hir_id); + + // Put the lint store levels and passes back in the session. + let passes = cx.lint_sess.passes; + drop(cx.lint_sess.lints); + store.borrow_mut().late_module_passes = passes; +} + +pub(crate) fn provide(providers: &mut Providers<'_>) { + *providers = Providers { + lint_mod, + ..*providers + }; +} + +fn lint_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let krate = tcx.hir().krate(); @@ -1225,6 +1275,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { }, last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, + only_module: false, }; // Visit the whole crate. @@ -1244,6 +1295,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.sess.lint_store.borrow_mut().late_passes = passes; } +/// Performs lint checking on a crate. +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + // Run per-module lints + for &module in tcx.hir().krate().modules.keys() { + tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); + } + + // Run whole crate non-incremental lints + lint_crate(tcx); +} + struct EarlyLintPassObjects<'a> { lints: &'a mut [EarlyLintPassObject], } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index ae44210bcfffc..cf1c5d50000fa 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -824,6 +824,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> { pub fn provide(providers: &mut Providers<'_>) { providers.lint_levels = lint_levels; + context::provide(providers); } /// Returns whether `span` originates in a foreign crate's external macro. diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index a2d7815920e0b..86299b29f48c9 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -245,6 +245,8 @@ rustc_query_append! { [define_queries!][ <'tcx> }, Other { + [] fn lint_mod: LintMod(DefId) -> (), + /// Checks the attributes in the module [] fn check_mod_attrs: CheckModAttrs(DefId) -> (), diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index e82e09c299765..099fd352680c2 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1272,6 +1272,7 @@ pub fn force_from_dep_node<'tcx>( DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); } DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); } DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); } + DepKind::LintMod => { force!(lint_mod, def_id!()); } DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); } DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); } DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c199829b298c0..b6daadb1b456f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -328,7 +328,7 @@ pub fn register_plugins<'a>( ls.register_early_pass(Some(sess), true, false, pass); } for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); + ls.register_late_pass(Some(sess), true, false, pass); } for (name, (to, deprecated_name)) in lint_groups { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 73a32f6d2003a..a5e5b570a4e63 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -125,37 +125,74 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new()); } - late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [ + // FIXME: Make a separate lint type which do not require typeck tables + + late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedModuleLateLintPass, [ HardwiredLints: HardwiredLints, WhileTrue: WhileTrue, ImproperCTypes: ImproperCTypes, VariantSizeDifferences: VariantSizeDifferences, BoxPointers: BoxPointers, - UnusedAttributes: UnusedAttributes, PathStatements: PathStatements, UnusedResults: UnusedResults, - NonSnakeCase: NonSnakeCase, NonUpperCaseGlobals: NonUpperCaseGlobals, NonShorthandFieldPatterns: NonShorthandFieldPatterns, UnusedAllocation: UnusedAllocation, + + // Depends on types used in type definitions MissingCopyImplementations: MissingCopyImplementations, - UnstableFeatures: UnstableFeatures, - InvalidNoMangleItems: InvalidNoMangleItems, + PluginAsLibrary: PluginAsLibrary, + + // Depends on referenced function signatures in expressions MutableTransmutes: MutableTransmutes, + + // Depends on types of fields, checks if they implement Drop UnionsWithDropFields: UnionsWithDropFields, - UnreachablePub: UnreachablePub, - UnnameableTestItems: UnnameableTestItems::new(), + TypeAliasBounds: TypeAliasBounds, + + // May Depend on constants elsewhere UnusedBrokenConst: UnusedBrokenConst, + TrivialConstraints: TrivialConstraints, TypeLimits: TypeLimits::new(), + ]], ['tcx]); + + store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new()); + + late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [ + + // Uses attr::is_used which is untracked, can't be an incremental module pass. + // Doesn't require type tables. Make a separate combined pass for that? + UnusedAttributes: UnusedAttributes, + + + // Checks crate attributes. Find out how that would work. + NonSnakeCase: NonSnakeCase, + + + // Needs to look at crate attributes. Make sure that works + UnstableFeatures: UnstableFeatures, + + // Depends on access levels + InvalidNoMangleItems: InvalidNoMangleItems, + + // Depends on access levels + UnreachablePub: UnreachablePub, + + UnnameableTestItems: UnnameableTestItems::new(), + + // Tracks attributes of parents MissingDoc: MissingDoc::new(), + + // Depends on access levels MissingDebugImplementations: MissingDebugImplementations::new(), + ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, ]], ['tcx]); - store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new()); + store.register_late_pass(sess, false, false, box BuiltinCombinedLateLintPass::new()); add_lint_group!(sess, "nonstandard_style", diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index bbd03e82a3730..b532e5c94d531 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1790,8 +1790,7 @@ fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { current_item: hir::DUMMY_HIR_ID, empty_tables: &empty_tables, }; - let (module, span, node_id) = tcx.hir().get_module(module_def_id); - let hir_id = tcx.hir().node_to_hir_id(node_id); + let (module, span, hir_id) = tcx.hir().get_module(module_def_id); intravisit::walk_mod(&mut visitor, module, hir_id); // Check privacy of explicitly written types and traits as well as From 32bc4a50c08e1710b2328de654bc0b281a1a5a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 3 Mar 2019 18:47:54 +0100 Subject: [PATCH 23/37] Make more lints incremental --- src/librustc/hir/map/mod.rs | 3 ++- src/librustc/lint/context.rs | 6 +++++ src/librustc_lint/lib.rs | 33 ++++++++++++-------------- src/librustc_lint/nonstandard_style.rs | 8 +++++-- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 56c3c71339f14..2ffb4959951b8 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1013,7 +1013,7 @@ impl<'hir> Map<'hir> { /// corresponding to the Node ID pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] { self.read(id); // reveals attributes on the node - let attrs = match self.find(id) { + let attrs = match self.find_entry(id).map(|entry| entry.node) { Some(Node::Local(l)) => Some(&l.attrs[..]), Some(Node::Item(i)) => Some(&i.attrs[..]), Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]), @@ -1027,6 +1027,7 @@ impl<'hir> Map<'hir> { // Unit/tuple structs/variants take the attributes straight from // the struct/variant definition. Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)), + Some(Node::Crate) => Some(&self.forest.krate.attrs[..]), _ => None }; attrs.unwrap_or(&[]) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6df3409d080e7..953d0116aa2ba 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -39,6 +39,7 @@ use errors::DiagnosticBuilder; use crate::hir; use crate::hir::def_id::{DefId, LOCAL_CRATE}; use crate::hir::intravisit as hir_visit; +use crate::hir::intravisit::Visitor; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; @@ -1244,6 +1245,11 @@ pub fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { let (module, span, hir_id) = tcx.hir().get_module(module_def_id); cx.process_mod(module, span, hir_id); + // Visit the crate attributes + if hir_id == hir::CRATE_HIR_ID { + walk_list!(cx, visit_attribute, cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID)); + } + // Put the lint store levels and passes back in the session. let passes = cx.lint_sess.passes; drop(cx.lint_sess.lints); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index a5e5b570a4e63..2caaa0159921b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -125,8 +125,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new()); } - // FIXME: Make a separate lint type which do not require typeck tables - late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedModuleLateLintPass, [ HardwiredLints: HardwiredLints, WhileTrue: WhileTrue, @@ -134,7 +132,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { VariantSizeDifferences: VariantSizeDifferences, BoxPointers: BoxPointers, PathStatements: PathStatements, + + // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, + NonUpperCaseGlobals: NonUpperCaseGlobals, NonShorthandFieldPatterns: NonShorthandFieldPatterns, UnusedAllocation: UnusedAllocation, @@ -157,39 +158,35 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { TrivialConstraints: TrivialConstraints, TypeLimits: TypeLimits::new(), + + NonSnakeCase: NonSnakeCase, + InvalidNoMangleItems: InvalidNoMangleItems, + + // Depends on access levels + UnreachablePub: UnreachablePub, + + ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, ]], ['tcx]); store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new()); late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [ - // Uses attr::is_used which is untracked, can't be an incremental module pass. - // Doesn't require type tables. Make a separate combined pass for that? UnusedAttributes: UnusedAttributes, - - // Checks crate attributes. Find out how that would work. - NonSnakeCase: NonSnakeCase, - - - // Needs to look at crate attributes. Make sure that works + // Needs to run after UnusedAttributes as it marks all `feature` attributes as used. UnstableFeatures: UnstableFeatures, - // Depends on access levels - InvalidNoMangleItems: InvalidNoMangleItems, - - // Depends on access levels - UnreachablePub: UnreachablePub, - + // Tracks state across modules UnnameableTestItems: UnnameableTestItems::new(), // Tracks attributes of parents MissingDoc: MissingDoc::new(), // Depends on access levels + // FIXME: Turn the computation of types which implement Debug into a query + // and change this to a module lint pass MissingDebugImplementations: MissingDebugImplementations::new(), - - ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, ]], ['tcx]); store.register_late_pass(sess, false, false, box BuiltinCombinedLateLintPass::new()); diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index fa18dd1eb8ddb..7a164dbcdf12d 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -267,11 +267,15 @@ impl LintPass for NonSnakeCase { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { - fn check_crate(&mut self, cx: &LateContext<'_, '_>, cr: &hir::Crate) { + fn check_mod(&mut self, cx: &LateContext<'_, '_>, _: &'tcx hir::Mod, _: Span, id: hir::HirId) { + if id != hir::CRATE_HIR_ID { + return; + } + let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name { Some(Ident::from_str(name)) } else { - attr::find_by_name(&cr.attrs, "crate_name") + attr::find_by_name(&cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID), "crate_name") .and_then(|attr| attr.meta()) .and_then(|meta| { meta.name_value_literal().and_then(|lit| { From 00d8fa3fdb3392916b45fc8e86ed0346fce4ffee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 13 Mar 2019 02:55:37 +0100 Subject: [PATCH 24/37] Update tests --- src/test/ui/lint/lint-impl-fn.stderr | 16 ++++++------- src/test/ui/lint/suggestions.stderr | 36 ++++++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/test/ui/lint/lint-impl-fn.stderr b/src/test/ui/lint/lint-impl-fn.stderr index 2c9a264287c96..56f85111d428f 100644 --- a/src/test/ui/lint/lint-impl-fn.stderr +++ b/src/test/ui/lint/lint-impl-fn.stderr @@ -11,25 +11,25 @@ LL | #[deny(while_true)] | ^^^^^^^^^^ error: denote infinite loops with `loop { ... }` - --> $DIR/lint-impl-fn.rs:18:25 + --> $DIR/lint-impl-fn.rs:27:5 | -LL | fn foo(&self) { while true {} } - | ^^^^^^^^^^ help: use `loop` +LL | while true {} + | ^^^^^^^^^^ help: use `loop` | note: lint level defined here - --> $DIR/lint-impl-fn.rs:13:8 + --> $DIR/lint-impl-fn.rs:25:8 | LL | #[deny(while_true)] | ^^^^^^^^^^ error: denote infinite loops with `loop { ... }` - --> $DIR/lint-impl-fn.rs:27:5 + --> $DIR/lint-impl-fn.rs:18:25 | -LL | while true {} - | ^^^^^^^^^^ help: use `loop` +LL | fn foo(&self) { while true {} } + | ^^^^^^^^^^ help: use `loop` | note: lint level defined here - --> $DIR/lint-impl-fn.rs:25:8 + --> $DIR/lint-impl-fn.rs:13:8 | LL | #[deny(while_true)] | ^^^^^^^^^^ diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index c28814aeee8f9..5aaa9947f998a 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -65,6 +65,24 @@ LL | pub fn defiant(_t: T) {} | = note: #[warn(no_mangle_generic_items)] on by default +warning: denote infinite loops with `loop { ... }` + --> $DIR/suggestions.rs:46:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + +warning: the `warp_factor:` in this pattern is redundant + --> $DIR/suggestions.rs:61:23 + | +LL | Equinox { warp_factor: warp_factor } => {} + | ------------^^^^^^^^^^^^ + | | + | help: remove this + | + = note: #[warn(non_shorthand_field_patterns)] on by default + error: const items should never be #[no_mangle] --> $DIR/suggestions.rs:22:18 | @@ -97,23 +115,5 @@ LL | #[no_mangle] pub(crate) fn crossfield() {} | | | help: remove this attribute -warning: denote infinite loops with `loop { ... }` - --> $DIR/suggestions.rs:46:5 - | -LL | while true { - | ^^^^^^^^^^ help: use `loop` - | - = note: #[warn(while_true)] on by default - -warning: the `warp_factor:` in this pattern is redundant - --> $DIR/suggestions.rs:61:23 - | -LL | Equinox { warp_factor: warp_factor } => {} - | ------------^^^^^^^^^^^^ - | | - | help: remove this - | - = note: #[warn(non_shorthand_field_patterns)] on by default - error: aborting due to 3 previous errors From 4bad56e54c1a870377b04b0b7f17e3051f246248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 25 Mar 2019 19:11:41 -0700 Subject: [PATCH 25/37] When moving out of a for loop head, suggest borrowing it in nll mode --- .../borrow_check/error_reporting.rs | 47 +++++++++++++++---- .../borrow_check/nll/explain_borrow/mod.rs | 18 ++++--- src/test/ui/augmented-assignments.nll.stderr | 17 ++----- ...-bound-on-closure-outlives-call.nll.stderr | 9 ++-- ...owck-call-is-borrow-issue-12224.nll.stderr | 1 - .../borrow-for-loop-head.nll.stderr | 9 ++-- 6 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 14289381aef45..88ff231202085 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -19,6 +19,7 @@ use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; +use syntax::source_map::CompilerDesugaringKind; use super::borrow_set::BorrowData; use super::{Context, MirBorrowckCtxt}; @@ -154,6 +155,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, format!("value moved{} here, in previous iteration of loop", move_msg), ); + if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() { + if let Ok(snippet) = self.infcx.tcx.sess.source_map() + .span_to_snippet(span) + { + err.span_suggestion( + move_span, + "consider borrowing this to avoid moving it into the for loop", + format!("&{}", snippet), + Applicability::MaybeIncorrect, + ); + } + } is_loop_move = true; } else if move_site.traversed_back_edge { err.span_label( @@ -291,8 +304,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { format!("move occurs due to use{}", move_spans.describe()) ); - self.explain_why_borrow_contains_point(context, borrow, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + self.explain_why_borrow_contains_point( + context, + borrow, + None, + ).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span)); err.buffer(&mut self.errors_buffer); } @@ -329,7 +345,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }); self.explain_why_borrow_contains_point(context, borrow, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); err.buffer(&mut self.errors_buffer); } @@ -542,8 +558,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { )); } - explanation - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc); + explanation.add_explanation_to_diagnostic( + self.infcx.tcx, + self.mir, + &mut err, + first_borrow_desc, + None, + ); err.buffer(&mut self.errors_buffer); } @@ -866,7 +887,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let BorrowExplanation::MustBeValidFor { .. } = explanation { } else { - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic( + self.infcx.tcx, + self.mir, + &mut err, + "", + None, + ); } } else { err.span_label(borrow_span, "borrowed value does not live long enough"); @@ -886,7 +913,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { format!("value captured here{}", within), ); - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); } err @@ -946,7 +973,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => {} } - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); err.buffer(&mut self.errors_buffer); } @@ -1027,7 +1054,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } _ => {} } - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); let within = if borrow_spans.for_generator() { " by generator" @@ -1367,7 +1394,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); self.explain_why_borrow_contains_point(context, loan, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); err.buffer(&mut self.errors_buffer); } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index dfa5af444d37e..67b77605f3c92 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -56,17 +56,23 @@ impl BorrowExplanation { mir: &Mir<'tcx>, err: &mut DiagnosticBuilder<'_>, borrow_desc: &str, + borrow_span: Option, ) { match *self { BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => { let message = match later_use_kind { - LaterUseKind::TraitCapture => "borrow later captured here by trait object", - LaterUseKind::ClosureCapture => "borrow later captured here by closure", - LaterUseKind::Call => "borrow later used by call", - LaterUseKind::FakeLetRead => "borrow later stored here", - LaterUseKind::Other => "borrow later used here", + LaterUseKind::TraitCapture => "captured here by trait object", + LaterUseKind::ClosureCapture => "captured here by closure", + LaterUseKind::Call => "used by call", + LaterUseKind::FakeLetRead => "stored here", + LaterUseKind::Other => "used here", }; - err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message)); + if !borrow_span.map(|sp| sp.overlaps(var_or_use_span)).unwrap_or(false) { + err.span_label( + var_or_use_span, + format!("{}borrow later {}", borrow_desc, message), + ); + } } BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => { let message = match later_use_kind { diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr index 08f06e90162b4..e205e2a87810f 100644 --- a/src/test/ui/augmented-assignments.nll.stderr +++ b/src/test/ui/augmented-assignments.nll.stderr @@ -1,18 +1,11 @@ error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/augmented-assignments.rs:16:5 | -LL | x - | - - | | - | _____borrow of `x` occurs here - | | -LL | | -LL | | += -LL | | x; - | | ^ - | | | - | |_____move out of `x` occurs here - | borrow later used here +LL | x + | - borrow of `x` occurs here +... +LL | x; + | ^ move out of `x` occurs here error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/augmented-assignments.rs:21:5 diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr b/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr index bce310bafaa92..d455902ee8c07 100644 --- a/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr +++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr @@ -14,11 +14,10 @@ error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/region-bound-on-closure-outlives-call.rs:3:25 | LL | (|x| f(x))(call_rec(f)) - | ---------- ^ move out of `f` occurs here - | || | - | || borrow occurs due to use in closure - | |borrow of `f` occurs here - | borrow later used by call + | --- - ^ move out of `f` occurs here + | | | + | | borrow occurs due to use in closure + | borrow of `f` occurs here error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index 80dc3ef2f80f2..1a5ab7a7d56a0 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -42,7 +42,6 @@ LL | f(Box::new(|a| { | - ^^^ move out of `f` occurs here | | | borrow of `f` occurs here - | borrow later used by call LL | foo(f); | - move occurs due to use in closure diff --git a/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr index 6450f7f52a47b..96dbdec7074a9 100644 --- a/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr +++ b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr @@ -2,10 +2,7 @@ error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/borrow-for-loop-head.rs:4:18 | LL | for i in &a { - | -- - | | - | borrow of `a` occurs here - | borrow later used here + | -- borrow of `a` occurs here LL | for j in a { | ^ move out of `a` occurs here @@ -17,6 +14,10 @@ LL | let a = vec![1, 2, 3]; LL | for i in &a { LL | for j in a { | ^ value moved here, in previous iteration of loop +help: consider borrowing this to avoid moving it into the for loop + | +LL | for j in &a { + | ^^ error: aborting due to 2 previous errors From 630d5a489552e671bf9dc7c0e72c77b0a1ad353c Mon Sep 17 00:00:00 2001 From: kenta7777 Date: Tue, 26 Mar 2019 13:06:15 +0900 Subject: [PATCH 26/37] renames EvalContext to InterpretCx. --- src/librustc_mir/const_eval.rs | 28 +++++++++++----------- src/librustc_mir/interpret/cast.rs | 4 ++-- src/librustc_mir/interpret/eval_context.rs | 12 +++++----- src/librustc_mir/interpret/intrinsics.rs | 4 ++-- src/librustc_mir/interpret/machine.rs | 24 +++++++++---------- src/librustc_mir/interpret/mod.rs | 2 +- src/librustc_mir/interpret/operand.rs | 4 ++-- src/librustc_mir/interpret/operator.rs | 6 ++--- src/librustc_mir/interpret/place.rs | 6 ++--- src/librustc_mir/interpret/step.rs | 6 ++--- src/librustc_mir/interpret/terminator.rs | 4 ++-- src/librustc_mir/interpret/traits.rs | 4 ++-- src/librustc_mir/interpret/validity.rs | 8 +++---- src/librustc_mir/interpret/visitor.rs | 24 +++++++++---------- src/librustc_mir/transform/const_prop.rs | 4 ++-- 15 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 8c774e0d54cce..211573ab49a1c 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -22,7 +22,7 @@ use syntax::source_map::{Span, DUMMY_SP}; use crate::interpret::{self, PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer, RawConst, ConstValue, - EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup, + EvalResult, EvalError, EvalErrorKind, GlobalId, InterpretCx, StackPopCleanup, Allocation, AllocId, MemoryKind, snapshot, RefTracking, }; @@ -47,7 +47,7 @@ pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> CompileTimeEvalContext<'a, 'mir, 'tcx> { debug!("mk_eval_cx: {:?}", param_env); - EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new()) + InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new()) } pub(crate) fn eval_promoted<'a, 'mir, 'tcx>( @@ -116,7 +116,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>( // and try improving it down the road when more information is available let span = tcx.def_span(cid.instance.def_id()); let span = mir.map(|mir| mir.span).unwrap_or(span); - let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new()); + let mut ecx = InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new()); let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env); (r, ecx) } @@ -292,7 +292,7 @@ impl interpret::AllocMap for FxHashMap { } type CompileTimeEvalContext<'a, 'mir, 'tcx> = - EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>; + InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>; impl interpret::MayLeak for ! { #[inline(always)] @@ -317,12 +317,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> const STATIC_KIND: Option = None; // no copying of statics allowed #[inline(always)] - fn enforce_validity(_ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool { + fn enforce_validity(_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool { false // for now, we don't enforce validity } fn find_fn( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], dest: Option>, @@ -362,7 +362,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> } fn call_intrinsic( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], dest: PlaceTy<'tcx>, @@ -378,7 +378,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> } fn ptr_op( - _ecx: &EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>, _bin_op: mir::BinOp, _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, @@ -406,7 +406,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> } fn box_alloc( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, ) -> EvalResult<'tcx> { Err( @@ -414,7 +414,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> ) } - fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> { + fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> { { let steps = &mut ecx.machine.steps_since_detector_enabled; @@ -440,7 +440,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> #[inline(always)] fn tag_new_allocation( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, ptr: Pointer, _kind: MemoryKind, ) -> Pointer { @@ -449,7 +449,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> #[inline(always)] fn stack_push( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, ) -> EvalResult<'tcx> { Ok(()) } @@ -457,7 +457,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> /// Called immediately before a stack frame gets popped. #[inline(always)] fn stack_pop( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, _extra: (), ) -> EvalResult<'tcx> { Ok(()) @@ -504,7 +504,7 @@ pub fn const_variant_index<'a, 'tcx>( } pub fn error_to_const_error<'a, 'mir, 'tcx>( - ecx: &EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>, + ecx: &InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>, mut error: EvalError<'tcx> ) -> ConstEvalErr<'tcx> { error.print_backtrace(); diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 7543dd678d032..003c2182d0b45 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -9,9 +9,9 @@ use rustc::mir::interpret::{ use rustc::mir::CastKind; use rustc_apfloat::Float; -use super::{EvalContext, Machine, PlaceTy, OpTy, ImmTy, Immediate}; +use super::{InterpretCx, Machine, PlaceTy, OpTy, ImmTy, Immediate}; -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool { match ty.sty { ty::RawPtr(ty::TypeAndMut { ty, .. }) | diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index e81d0a56b2b05..8b7e28c3de077 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -26,7 +26,7 @@ use super::{ Memory, Machine }; -pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { +pub struct InterpretCx<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// Stores the `Machine` instance. pub machine: M, @@ -141,7 +141,7 @@ impl<'tcx, Tag> LocalState<'tcx, Tag> { } impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout - for EvalContext<'a, 'mir, 'tcx, M> + for InterpretCx<'a, 'mir, 'tcx, M> { #[inline] fn data_layout(&self) -> &layout::TargetDataLayout { @@ -149,7 +149,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout } } -impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for EvalContext<'a, 'mir, 'tcx, M> +impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'a, 'mir, 'tcx, M> where M: Machine<'a, 'mir, 'tcx> { #[inline] @@ -159,7 +159,7 @@ impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for EvalContext<'a, 'mir, 'tcx, } impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf - for EvalContext<'a, 'mir, 'tcx, M> + for InterpretCx<'a, 'mir, 'tcx, M> { type Ty = Ty<'tcx>; type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>; @@ -171,13 +171,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf } } -impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { pub fn new( tcx: TyCtxtAt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, machine: M, ) -> Self { - EvalContext { + InterpretCx { machine, tcx, param_env, diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index e002c3fd511d6..99dd654df21e3 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ }; use super::{ - Machine, PlaceTy, OpTy, EvalContext, + Machine, PlaceTy, OpTy, InterpretCx, }; @@ -36,7 +36,7 @@ fn numeric_intrinsic<'tcx, Tag>( Ok(Scalar::from_uint(bits_out, size)) } -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { /// Returns `true` if emulation happened. pub fn emulate_intrinsic( &mut self, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 7fb4c47d92acb..09d403ab243d6 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -11,7 +11,7 @@ use rustc::ty::{self, query::TyCtxtAt}; use super::{ Allocation, AllocId, EvalResult, Scalar, AllocationExtra, - EvalContext, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind, + InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind, }; /// Whether this kind of memory is allowed to leak @@ -95,11 +95,11 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { const STATIC_KIND: Option; /// Whether to enforce the validity invariant - fn enforce_validity(ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool; + fn enforce_validity(ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool; /// Called before a basic block terminator is executed. /// You can use this to detect endlessly running programs. - fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>; + fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>; /// Entry point to all function calls. /// @@ -112,7 +112,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them /// was used. fn find_fn( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::PointerTag>], dest: Option>, @@ -122,7 +122,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Directly process an intrinsic without pushing a stack frame. /// If this returns successfully, the engine will take care of jumping to the next block. fn call_intrinsic( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::PointerTag>], dest: PlaceTy<'tcx, Self::PointerTag>, @@ -156,7 +156,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// /// Returns a (value, overflowed) pair if the operation succeeded fn ptr_op( - ecx: &EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &InterpretCx<'a, 'mir, 'tcx, Self>, bin_op: mir::BinOp, left: ImmTy<'tcx, Self::PointerTag>, right: ImmTy<'tcx, Self::PointerTag>, @@ -164,13 +164,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Heap allocations via the `box` keyword. fn box_alloc( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, dest: PlaceTy<'tcx, Self::PointerTag>, ) -> EvalResult<'tcx>; /// Adds the tag for a newly allocated pointer. fn tag_new_allocation( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, ptr: Pointer, kind: MemoryKind, ) -> Pointer; @@ -180,7 +180,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// `mutability` can be `None` in case a raw ptr is being dereferenced. #[inline] fn tag_dereference( - _ecx: &EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>, place: MPlaceTy<'tcx, Self::PointerTag>, _mutability: Option, ) -> EvalResult<'tcx, Scalar> { @@ -190,7 +190,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Executes a retagging operation #[inline] fn retag( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, _kind: mir::RetagKind, _place: PlaceTy<'tcx, Self::PointerTag>, ) -> EvalResult<'tcx> { @@ -199,12 +199,12 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Called immediately before a new stack frame got pushed fn stack_push( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, ) -> EvalResult<'tcx, Self::FrameExtra>; /// Called immediately after a stack frame gets popped fn stack_pop( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, extra: Self::FrameExtra, ) -> EvalResult<'tcx>; } diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index d2ab3fcb7a30a..ea358389ddb76 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -18,7 +18,7 @@ mod visitor; pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here pub use self::eval_context::{ - EvalContext, Frame, StackPopCleanup, LocalState, LocalValue, + InterpretCx, Frame, StackPopCleanup, LocalState, LocalValue, }; pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy}; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 70511075e87c9..15b6d5c914d20 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -13,7 +13,7 @@ use rustc::mir::interpret::{ sign_extend, truncate, }; use super::{ - EvalContext, Machine, + InterpretCx, Machine, MemPlace, MPlaceTy, PlaceTy, Place, MemoryKind, }; pub use rustc::mir::interpret::ScalarMaybeUndef; @@ -267,7 +267,7 @@ pub(super) fn from_known_layout<'tcx>( } } -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { /// Try reading an immediate in memory; this is interesting particularly for ScalarPair. /// Returns `None` if the layout does not permit loading this as a value. fn try_read_immediate_from_mplace( diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 944e393d296fc..ca93007788e03 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -5,10 +5,10 @@ use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc::mir::interpret::{EvalResult, Scalar}; -use super::{EvalContext, PlaceTy, Immediate, Machine, ImmTy}; +use super::{InterpretCx, PlaceTy, Immediate, Machine, ImmTy}; -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { /// Applies the binary operation `op` to the two operands and writes a tuple of the result /// and a boolean signifying the potential overflow to the destination. pub fn binop_with_overflow( @@ -37,7 +37,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } } -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { fn binary_char_op( &self, bin_op: mir::BinOp, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 755bbd96b02f9..70c3e9f5a58bc 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -14,7 +14,7 @@ use rustc::ty::TypeFoldable; use super::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic, - EvalContext, Machine, AllocMap, AllocationExtra, + InterpretCx, Machine, AllocMap, AllocationExtra, RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind }; @@ -305,7 +305,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> { } // separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385 -impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M> +impl<'a, 'mir, 'tcx, Tag, M> InterpretCx<'a, 'mir, 'tcx, M> where // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static, @@ -606,7 +606,7 @@ where // global table but not in its local memory: It calls back into tcx through // a query, triggering the CTFE machinery to actually turn this lazy reference // into a bunch of bytes. IOW, statics are evaluated with CTFE even when - // this EvalContext uses another Machine (e.g., in miri). This is what we + // this InterpretCx uses another Machine (e.g., in miri). This is what we // want! This way, computing statics works concistently between codegen // and miri: They use the same query to eventually obtain a `ty::Const` // and use that for further computation. diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 656c13c16d9ed..29a8547035e4a 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -1,4 +1,4 @@ -//! This module contains the `EvalContext` methods for executing a single step of the interpreter. +//! This module contains the `InterpretCx` methods for executing a single step of the interpreter. //! //! The main entry point is the `step` method. @@ -6,7 +6,7 @@ use rustc::mir; use rustc::ty::layout::LayoutOf; use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic}; -use super::{EvalContext, Machine}; +use super::{InterpretCx, Machine}; /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the /// same type as the result. @@ -35,7 +35,7 @@ fn binop_right_homogeneous(op: mir::BinOp) -> bool { } } -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { pub fn run(&mut self) -> EvalResult<'tcx> { while self.step()? {} Ok(()) diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 83469d749870f..01965f53c157d 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -7,10 +7,10 @@ use rustc_target::spec::abi::Abi; use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar}; use super::{ - EvalContext, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup + InterpretCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup }; -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { #[inline] pub fn goto_block(&mut self, target: Option) -> EvalResult<'tcx> { if let Some(target) = target { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 1b0a9b17d3686..cce6c95a31240 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -3,9 +3,9 @@ use rustc::ty::{self, Ty}; use rustc::ty::layout::{Size, Align, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; -use super::{EvalContext, Machine, MemoryKind}; +use super::{InterpretCx, Machine, MemoryKind}; -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { /// Creates a dynamic vtable for the given type and vtable origin. This is used only for /// objects. /// diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 252e8bac2a3f8..3323ec387bfd5 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ }; use super::{ - OpTy, Machine, EvalContext, ValueVisitor, MPlaceTy, + OpTy, Machine, InterpretCx, ValueVisitor, MPlaceTy, }; macro_rules! validation_failure { @@ -153,7 +153,7 @@ struct ValidityVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir, M: Machine<'a path: Vec, ref_tracking: Option<&'rt mut RefTracking>>, const_mode: bool, - ecx: &'rt EvalContext<'a, 'mir, 'tcx, M>, + ecx: &'rt InterpretCx<'a, 'mir, 'tcx, M>, } impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> { @@ -224,7 +224,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> type V = OpTy<'tcx, M::PointerTag>; #[inline(always)] - fn ecx(&self) -> &EvalContext<'a, 'mir, 'tcx, M> { + fn ecx(&self) -> &InterpretCx<'a, 'mir, 'tcx, M> { &self.ecx } @@ -587,7 +587,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> } } -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> { /// This function checks the data at `op`. `op` is assumed to cover valid memory if it /// is an indirect operand. /// It will error if the bits at the destination do not match the ones described by the layout. diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index e2abf2ffc849c..90d4fff421837 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -8,7 +8,7 @@ use rustc::mir::interpret::{ }; use super::{ - Machine, EvalContext, MPlaceTy, OpTy, + Machine, InterpretCx, MPlaceTy, OpTy, }; // A thing that we can project into, and that has a layout. @@ -22,7 +22,7 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy /// Makes this into an `OpTy`. fn to_op( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>; /// Creates this from an `MPlaceTy`. @@ -31,14 +31,14 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy /// Projects to the given enum variant. fn project_downcast( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, variant: VariantIdx, ) -> EvalResult<'tcx, Self>; /// Projects to the n-th field. fn project_field( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, field: u64, ) -> EvalResult<'tcx, Self>; } @@ -56,7 +56,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> #[inline(always)] fn to_op( self, - _ecx: &EvalContext<'a, 'mir, 'tcx, M>, + _ecx: &InterpretCx<'a, 'mir, 'tcx, M>, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { Ok(self) } @@ -69,7 +69,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> #[inline(always)] fn project_downcast( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, variant: VariantIdx, ) -> EvalResult<'tcx, Self> { ecx.operand_downcast(self, variant) @@ -78,7 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> #[inline(always)] fn project_field( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, field: u64, ) -> EvalResult<'tcx, Self> { ecx.operand_field(self, field) @@ -95,7 +95,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> #[inline(always)] fn to_op( self, - _ecx: &EvalContext<'a, 'mir, 'tcx, M>, + _ecx: &InterpretCx<'a, 'mir, 'tcx, M>, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { Ok(self.into()) } @@ -108,7 +108,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> #[inline(always)] fn project_downcast( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, variant: VariantIdx, ) -> EvalResult<'tcx, Self> { ecx.mplace_downcast(self, variant) @@ -117,7 +117,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> #[inline(always)] fn project_field( self, - ecx: &EvalContext<'a, 'mir, 'tcx, M>, + ecx: &InterpretCx<'a, 'mir, 'tcx, M>, field: u64, ) -> EvalResult<'tcx, Self> { ecx.mplace_field(self, field) @@ -130,9 +130,9 @@ macro_rules! make_value_visitor { pub trait $visitor_trait_name<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized { type V: Value<'a, 'mir, 'tcx, M>; - /// The visitor must have an `EvalContext` in it. + /// The visitor must have an `InterpretCx` in it. fn ecx(&$($mutability)? self) - -> &$($mutability)? EvalContext<'a, 'mir, 'tcx, M>; + -> &$($mutability)? InterpretCx<'a, 'mir, 'tcx, M>; // Recursive actions, ready to be overloaded. /// Visits the given value, dispatching as appropriate to more specialized visitors. diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 33672a2b7745c..dd84aa5d5530a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -18,7 +18,7 @@ use rustc::ty::layout::{ HasTyCtxt, TargetDataLayout, HasDataLayout, }; -use crate::interpret::{EvalContext, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind}; +use crate::interpret::{InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind}; use crate::const_eval::{ CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx, }; @@ -70,7 +70,7 @@ type Const<'tcx> = (OpTy<'tcx>, Span); /// Finds optimization opportunities on the MIR. struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> { - ecx: EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>, + ecx: InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>, mir: &'mir Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource<'tcx>, From 0e0383abc6d1f7d1edc456f66a2e3f4082e9a0a8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 18 Mar 2019 22:45:02 +0100 Subject: [PATCH 27/37] adjust MaybeUninit API to discussions uninitialized -> uninit into_initialized -> assume_init read_initialized -> read set -> write --- src/liballoc/collections/btree/node.rs | 10 +-- src/libcore/fmt/float.rs | 16 ++-- src/libcore/fmt/num.rs | 4 +- src/libcore/macros.rs | 4 +- src/libcore/mem.rs | 110 ++++++++++++++++--------- src/libcore/ptr.rs | 14 ++-- src/libcore/slice/rotate.rs | 2 +- 7 files changed, 97 insertions(+), 63 deletions(-) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 66d619b1298b4..581c66c7086a5 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -109,7 +109,7 @@ impl LeafNode { keys: uninitialized_array![_; CAPACITY], vals: uninitialized_array![_; CAPACITY], parent: ptr::null(), - parent_idx: MaybeUninit::uninitialized(), + parent_idx: MaybeUninit::uninit(), len: 0 } } @@ -129,7 +129,7 @@ unsafe impl Sync for NodeHeader<(), ()> {} // ever take a pointer past the first key. static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader { parent: ptr::null(), - parent_idx: MaybeUninit::uninitialized(), + parent_idx: MaybeUninit::uninit(), len: 0, keys_start: [], }; @@ -261,7 +261,7 @@ impl Root { -> NodeRef, K, V, marker::Internal> { debug_assert!(!self.is_shared_root()); let mut new_node = Box::new(unsafe { InternalNode::new() }); - new_node.edges[0].set(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) }); + new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) }); self.node = BoxedNode::from_internal(new_node); self.height += 1; @@ -737,7 +737,7 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { unsafe { ptr::write(self.keys_mut().get_unchecked_mut(idx), key); ptr::write(self.vals_mut().get_unchecked_mut(idx), val); - self.as_internal_mut().edges.get_unchecked_mut(idx + 1).set(edge.node); + self.as_internal_mut().edges.get_unchecked_mut(idx + 1).write(edge.node); (*self.as_leaf_mut()).len += 1; @@ -1080,7 +1080,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let mut child = self.descend(); unsafe { (*child.as_leaf_mut()).parent = ptr; - (*child.as_leaf_mut()).parent_idx.set(idx); + (*child.as_leaf_mut()).parent_idx.write(idx); } } diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index edeb65afd67b2..5f4c6f7b0a3f0 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -10,8 +10,8 @@ fn float_to_decimal_common_exact(fmt: &mut Formatter, num: &T, where T: flt2dec::DecodableFloat { unsafe { - let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 - let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); + let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64 + let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninit(); // FIXME(#53491): Technically, this is calling `get_mut` on an uninitialized // `MaybeUninit` (here and elsewhere in this file). Revisit this once // we decided whether that is valid or not. @@ -32,8 +32,8 @@ fn float_to_decimal_common_shortest(fmt: &mut Formatter, num: &T, { unsafe { // enough for f32 and f64 - let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized(); - let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); + let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit(); + let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninit(); // FIXME(#53491) let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, sign, precision, false, buf.get_mut(), @@ -71,8 +71,8 @@ fn float_to_exponential_common_exact(fmt: &mut Formatter, num: &T, where T: flt2dec::DecodableFloat { unsafe { - let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 - let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized(); + let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64 + let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninit(); // FIXME(#53491) let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, *num, sign, precision, @@ -91,8 +91,8 @@ fn float_to_exponential_common_shortest(fmt: &mut Formatter, { unsafe { // enough for f32 and f64 - let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized(); - let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized(); + let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit(); + let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninit(); // FIXME(#53491) let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, *num, sign, (0, 0), upper, diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index b9fa364037108..e96dbcaa14416 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -60,7 +60,7 @@ trait GenericRadix { for byte in buf.iter_mut().rev() { let n = x % base; // Get the current place value. x = x / base; // Deaccumulate the number. - byte.set(Self::digit(n.to_u8())); // Store the digit in the buffer. + byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer. curr -= 1; if x == zero { // No more digits left to accumulate. @@ -72,7 +72,7 @@ trait GenericRadix { for byte in buf.iter_mut().rev() { let n = zero - (x % base); // Get the current place value. x = x / base; // Deaccumulate the number. - byte.set(Self::digit(n.to_u8())); // Store the digit in the buffer. + byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer. curr -= 1; if x == zero { // No more digits left to accumulate. diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d77936c7ddd91..ad8ce1af1f6a1 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -626,12 +626,12 @@ macro_rules! todo { #[macro_export] #[unstable(feature = "maybe_uninit_array", issue = "53491")] macro_rules! uninitialized_array { - // This `into_initialized` is safe because an array of `MaybeUninit` does not + // This `assume_init` is safe because an array of `MaybeUninit` does not // require initialization. // FIXME(#49147): Could be replaced by an array initializer, once those can // be any const expression. ($t:ty; $size:expr) => (unsafe { - MaybeUninit::<[MaybeUninit<$t>; $size]>::uninitialized().into_initialized() + MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init() }); } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 3d2fcdc979377..66bcf1f7d0101 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -622,7 +622,7 @@ pub unsafe fn zeroed() -> T { /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html #[inline] -#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")] +#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized() -> T { intrinsics::panic_if_uninhabited::(); @@ -1058,7 +1058,7 @@ impl DerefMut for ManuallyDrop { /// /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! /// // The equivalent code with `MaybeUninit<&i32>`: -/// let x: &i32 = unsafe { MaybeUninit::zeroed().into_initialized() }; // undefined behavior! +/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! /// ``` /// /// This is exploited by the compiler for various optimizations, such as eliding @@ -1073,7 +1073,7 @@ impl DerefMut for ManuallyDrop { /// /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! /// // The equivalent code with `MaybeUninit`: -/// let b: bool = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior! +/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! /// ``` /// /// Moreover, uninitialized memory is special in that the compiler knows that @@ -1087,7 +1087,7 @@ impl DerefMut for ManuallyDrop { /// /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! /// // The equivalent code with `MaybeUninit`: -/// let x: i32 = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior! +/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! /// ``` /// (Notice that the rules around uninitialized integers are not finalized yet, but /// until they are, it is advisable to avoid them.) @@ -1102,12 +1102,12 @@ impl DerefMut for ManuallyDrop { /// /// // Create an explicitly uninitialized reference. The compiler knows that data inside /// // a `MaybeUninit` may be invalid, and hence this is not UB: -/// let mut x = MaybeUninit::<&i32>::uninitialized(); +/// let mut x = MaybeUninit::<&i32>::uninit(); /// // Set it to a valid value. -/// x.set(&0); +/// x.write(&0); /// // Extract the initialized data -- this is only allowed *after* properly /// // initializing `x`! -/// let x = unsafe { x.into_initialized() }; +/// let x = unsafe { x.assume_init() }; /// ``` /// /// The compiler then knows to not make any incorrect assumptions or optimizations on this code. @@ -1148,10 +1148,19 @@ impl MaybeUninit { /// It is your responsibility to make sure `T` gets dropped if it got initialized. #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] - pub const fn uninitialized() -> MaybeUninit { + pub const fn uninit() -> MaybeUninit { MaybeUninit { uninit: () } } + /// Deprecated before stabilization. + #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] + // FIXME: still used by stdsimd + // #[rustc_deprecated(since = "1.35.0", reason = "use `uninit` instead")] + pub const fn uninitialized() -> MaybeUninit { + Self::uninit() + } + /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being /// filled with `0` bytes. It depends on `T` whether that already makes for /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, @@ -1171,7 +1180,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::<(u8, bool)>::zeroed(); - /// let x = unsafe { x.into_initialized() }; + /// let x = unsafe { x.assume_init() }; /// assert_eq!(x, (0, false)); /// ``` /// @@ -1185,14 +1194,14 @@ impl MaybeUninit { /// enum NotZero { One = 1, Two = 2 }; /// /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); - /// let x = unsafe { x.into_initialized() }; + /// let x = unsafe { x.assume_init() }; /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. /// // This is undefined behavior. /// ``` #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline] pub fn zeroed() -> MaybeUninit { - let mut u = MaybeUninit::::uninitialized(); + let mut u = MaybeUninit::::uninit(); unsafe { u.as_mut_ptr().write_bytes(0u8, 1); } @@ -1205,13 +1214,21 @@ impl MaybeUninit { /// reference to the (now safely initialized) contents of `self`. #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] - pub fn set(&mut self, val: T) -> &mut T { + pub fn write(&mut self, val: T) -> &mut T { unsafe { self.value = ManuallyDrop::new(val); self.get_mut() } } + /// Deprecated before stabilization. + #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] + #[rustc_deprecated(since = "1.35.0", reason = "use `write` instead")] + pub fn set(&mut self, val: T) -> &mut T { + self.write(val) + } + /// Gets a pointer to the contained value. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. /// @@ -1223,7 +1240,7 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let mut x = MaybeUninit::>::uninitialized(); + /// let mut x = MaybeUninit::>::uninit(); /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. /// let x_vec = unsafe { &*x.as_ptr() }; @@ -1236,7 +1253,7 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let x = MaybeUninit::>::uninitialized(); + /// let x = MaybeUninit::>::uninit(); /// let x_vec = unsafe { &*x.as_ptr() }; /// // We have created a reference to an uninitialized vector! This is undefined behavior. /// ``` @@ -1260,7 +1277,7 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let mut x = MaybeUninit::>::uninitialized(); + /// let mut x = MaybeUninit::>::uninit(); /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } /// // Create a reference into the `MaybeUninit>`. /// // This is okay because we initialized it. @@ -1275,7 +1292,7 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let mut x = MaybeUninit::>::uninitialized(); + /// let mut x = MaybeUninit::>::uninit(); /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; /// // We have created a reference to an uninitialized vector! This is undefined behavior. /// ``` @@ -1306,9 +1323,9 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let mut x = MaybeUninit::::uninitialized(); + /// let mut x = MaybeUninit::::uninit(); /// unsafe { x.as_mut_ptr().write(true); } - /// let x_init = unsafe { x.into_initialized() }; + /// let x_init = unsafe { x.assume_init() }; /// assert_eq!(x_init, true); /// ``` /// @@ -1318,21 +1335,30 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let x = MaybeUninit::>::uninitialized(); - /// let x_init = unsafe { x.into_initialized() }; + /// let x = MaybeUninit::>::uninit(); + /// let x_init = unsafe { x.assume_init() }; /// // `x` had not been initialized yet, so this last line caused undefined behavior. /// ``` #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] - pub unsafe fn into_initialized(self) -> T { + pub unsafe fn assume_init(self) -> T { intrinsics::panic_if_uninhabited::(); ManuallyDrop::into_inner(self.value) } + /// Deprecated before stabilization. + #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] + // FIXME: still used by stdsimd + // #[rustc_deprecated(since = "1.35.0", reason = "use `assume_init` instead")] + pub unsafe fn into_initialized(self) -> T { + self.assume_init() + } + /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject /// to the usual drop handling. /// - /// Whenever possible, it is preferrable to use [`into_initialized`] instead, which + /// Whenever possible, it is preferrable to use [`assume_init`] instead, which /// prevents duplicating the content of the `MaybeUninit`. /// /// # Safety @@ -1342,11 +1368,11 @@ impl MaybeUninit { /// behavior. /// /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit`. When using - /// multiple copies of the data (by calling `read_initialized` multiple times, or first - /// calling `read_initialized` and then [`into_initialized`]), it is your responsibility + /// multiple copies of the data (by calling `read` multiple times, or first + /// calling `read` and then [`assume_init`]), it is your responsibility /// to ensure that that data may indeed be duplicated. /// - /// [`into_initialized`]: #method.into_initialized + /// [`assume_init`]: #method.assume_init /// /// # Examples /// @@ -1356,18 +1382,18 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let mut x = MaybeUninit::::uninitialized(); - /// x.set(13); - /// let x1 = unsafe { x.read_initialized() }; + /// let mut x = MaybeUninit::::uninit(); + /// x.write(13); + /// let x1 = unsafe { x.read() }; /// // `u32` is `Copy`, so we may read multiple times. - /// let x2 = unsafe { x.read_initialized() }; + /// let x2 = unsafe { x.read() }; /// assert_eq!(x1, x2); /// - /// let mut x = MaybeUninit::>>::uninitialized(); - /// x.set(None); - /// let x1 = unsafe { x.read_initialized() }; + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(None); + /// let x1 = unsafe { x.read() }; /// // Duplicating a `None` value is okay, so we may read multiple times. - /// let x2 = unsafe { x.read_initialized() }; + /// let x2 = unsafe { x.read() }; /// assert_eq!(x1, x2); /// ``` /// @@ -1377,20 +1403,28 @@ impl MaybeUninit { /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// - /// let mut x = MaybeUninit::>>::uninitialized(); - /// x.set(Some(vec![0,1,2])); - /// let x1 = unsafe { x.read_initialized() }; - /// let x2 = unsafe { x.read_initialized() }; + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(Some(vec![0,1,2])); + /// let x1 = unsafe { x.read() }; + /// let x2 = unsafe { x.read() }; /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] - pub unsafe fn read_initialized(&self) -> T { + pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::(); self.as_ptr().read() } + /// Deprecated before stabilization. + #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] + #[rustc_deprecated(since = "1.35.0", reason = "use `read` instead")] + pub unsafe fn read_initialized(&self) -> T { + self.read() + } + /// Gets a reference to the contained value. /// /// # Safety diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index a9a029d606d6f..1cb21aa6be0a2 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -296,7 +296,7 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } pub unsafe fn swap(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. - let mut tmp = MaybeUninit::::uninitialized(); + let mut tmp = MaybeUninit::::uninit(); // Perform the swap copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); @@ -388,7 +388,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t = mem::MaybeUninit::::uninitialized(); + let mut t = mem::MaybeUninit::::uninit(); let t = t.as_mut_ptr() as *mut u8; let x = x.add(i); let y = y.add(i); @@ -403,7 +403,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { if i < len { // Swap any remaining bytes - let mut t = mem::MaybeUninit::::uninitialized(); + let mut t = mem::MaybeUninit::::uninit(); let rem = len - i; let t = t.as_mut_ptr() as *mut u8; @@ -571,9 +571,9 @@ pub unsafe fn replace(dst: *mut T, mut src: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read(src: *const T) -> T { - let mut tmp = MaybeUninit::::uninitialized(); + let mut tmp = MaybeUninit::::uninit(); copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); - tmp.into_initialized() + tmp.assume_init() } /// Reads the value from `src` without moving it. This leaves the @@ -638,11 +638,11 @@ pub unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn read_unaligned(src: *const T) -> T { - let mut tmp = MaybeUninit::::uninitialized(); + let mut tmp = MaybeUninit::::uninit(); copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::()); - tmp.into_initialized() + tmp.assume_init() } /// Overwrites a memory location with the given value without reading or diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 9b35b51349a02..8f10c3576a787 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -72,7 +72,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { } } - let mut rawarray = MaybeUninit::>::uninitialized(); + let mut rawarray = MaybeUninit::>::uninit(); let buf = &mut (*rawarray.as_mut_ptr()).typed as *mut [T; 2] as *mut T; let dim = mid.sub(left).add(right); From 853ae8d931c3fe4cd303edf7d80271c1930b9654 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 19 Mar 2019 09:46:11 +0100 Subject: [PATCH 28/37] fix some uses I missed --- src/libstd/sys/sgx/ext/arch.rs | 8 ++++---- src/libstd/sys/sgx/rwlock.rs | 2 +- src/libstd/sys/windows/mutex.rs | 2 +- src/test/codegen/box-maybe-uninit.rs | 5 ++++- src/test/run-pass/panic-uninitialized-zeroed.rs | 6 +++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libstd/sys/sgx/ext/arch.rs b/src/libstd/sys/sgx/ext/arch.rs index 53fb371947a99..5056e388112ce 100644 --- a/src/libstd/sys/sgx/ext/arch.rs +++ b/src/libstd/sys/sgx/ext/arch.rs @@ -28,7 +28,7 @@ const ENCLU_EGETKEY: u32 = 1; #[unstable(feature = "sgx_platform", issue = "56975")] pub fn egetkey(request: &Align512<[u8; 512]>) -> Result, u32> { unsafe { - let mut out = MaybeUninit::uninitialized(); + let mut out = MaybeUninit::uninit(); let error; asm!( @@ -41,7 +41,7 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result, u32> ); match error { - 0 => Ok(out.into_initialized()), + 0 => Ok(out.assume_init()), err => Err(err), } } @@ -58,7 +58,7 @@ pub fn ereport( reportdata: &Align128<[u8; 64]>, ) -> Align512<[u8; 432]> { unsafe { - let mut report = MaybeUninit::uninitialized(); + let mut report = MaybeUninit::uninit(); asm!( "enclu" @@ -69,6 +69,6 @@ pub fn ereport( "{rdx}"(report.as_mut_ptr()) ); - report.into_initialized() + report.assume_init() } } diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 7b113267865b6..7e2d13b9e2476 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -280,7 +280,7 @@ mod tests { let mut init = MaybeUninit::::zeroed(); rwlock_new(&mut init); assert_eq!( - mem::transmute::<_, [u8; 128]>(init.into_initialized()).as_slice(), + mem::transmute::<_, [u8; 128]>(init.assume_init()).as_slice(), RWLOCK_INIT ) }; diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 1aa910f05c9c3..37cbdcefcedcc 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -154,7 +154,7 @@ unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { pub fn uninitialized() -> ReentrantMutex { - ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninitialized()) } + ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) } } pub unsafe fn init(&mut self) { diff --git a/src/test/codegen/box-maybe-uninit.rs b/src/test/codegen/box-maybe-uninit.rs index ad1d259a0da21..0dd67bb95ccaa 100644 --- a/src/test/codegen/box-maybe-uninit.rs +++ b/src/test/codegen/box-maybe-uninit.rs @@ -12,5 +12,8 @@ pub fn box_uninitialized() -> Box> { // CHECK-NOT: alloca // CHECK-NOT: memcpy // CHECK-NOT: memset - Box::new(MaybeUninit::uninitialized()) + Box::new(MaybeUninit::uninit()) } + +// FIXME: add a test for a bigger box. Currently broken, see +// https://github.com/rust-lang/rust/issues/58201. diff --git a/src/test/run-pass/panic-uninitialized-zeroed.rs b/src/test/run-pass/panic-uninitialized-zeroed.rs index 31c0d2994d415..3f6e489bb8327 100644 --- a/src/test/run-pass/panic-uninitialized-zeroed.rs +++ b/src/test/run-pass/panic-uninitialized-zeroed.rs @@ -36,7 +36,7 @@ fn main() { assert_eq!( panic::catch_unwind(|| { - mem::MaybeUninit::::uninitialized().into_initialized() + mem::MaybeUninit::::uninit().assume_init() }).err().and_then(|a| a.downcast_ref::().map(|s| { s == "Attempted to instantiate uninhabited type !" })), @@ -63,7 +63,7 @@ fn main() { assert_eq!( panic::catch_unwind(|| { - mem::MaybeUninit::::uninitialized().into_initialized() + mem::MaybeUninit::::uninit().assume_init() }).err().and_then(|a| a.downcast_ref::().map(|s| { s == "Attempted to instantiate uninhabited type Foo" })), @@ -90,7 +90,7 @@ fn main() { assert_eq!( panic::catch_unwind(|| { - mem::MaybeUninit::::uninitialized().into_initialized() + mem::MaybeUninit::::uninit().assume_init() }).err().and_then(|a| a.downcast_ref::().map(|s| { s == "Attempted to instantiate uninhabited type Bar" })), From 6ea6e62075f21642bfd94b00bf641ea3fe4208c5 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 11:03:19 +0100 Subject: [PATCH 29/37] Update jemalloc-sys to version 0.3.0 --- src/rustc/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index e601a1f82377f..997d139383798 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -17,7 +17,7 @@ rustc_driver = { path = "../librustc_driver" } rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } [dependencies.jemalloc-sys] -version = '0.1.8' +version = '0.3.0' optional = true features = ['unprefixed_malloc_on_supported_platforms'] From b73886d9477f62b5b56439880f64b6d392589753 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 11:29:21 +0100 Subject: [PATCH 30/37] Update Cargo.lock --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec1cda96b99a6..188cfe73491be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1195,7 +1195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jemalloc-sys" -version = "0.1.8" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2066,7 +2066,7 @@ name = "rand_chacha" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2088,7 +2088,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2113,7 +2113,7 @@ name = "rand_xorshift" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2492,7 +2492,7 @@ dependencies = [ name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_codegen_ssa 0.0.0", "rustc_driver 0.0.0", "rustc_target 0.0.0", @@ -4086,7 +4086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" +"checksum jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bef0d4ce37578dfd80b466e3d8324bd9de788e249f1accebb0c472ea4b52bdc" "checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a5152c3fda235dfd68341b3edf4121bc4428642c93acbd6de88c26bf95fc5d7" From 4093bec80d39f94d69754d3a30cb14d9d4954424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 26 Mar 2019 17:04:00 +0100 Subject: [PATCH 31/37] Exclude UnusedBrokenConst from module lints --- src/librustc_lint/builtin.rs | 1 + src/librustc_lint/lib.rs | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 304e6eb712e3c..492ac1bf14dcc 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1360,6 +1360,7 @@ fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) { promoted: None }; // trigger the query once for all constants since that will already report the errors + // FIXME: Use ensure here let _ = cx.tcx.const_eval(param_env.and(cid)); } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2caaa0159921b..4c624a267af9b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -153,9 +153,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { TypeAliasBounds: TypeAliasBounds, - // May Depend on constants elsewhere - UnusedBrokenConst: UnusedBrokenConst, - TrivialConstraints: TrivialConstraints, TypeLimits: TypeLimits::new(), @@ -171,6 +168,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new()); late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [ + // FIXME: Look into regression when this is used as a module lint + // May Depend on constants elsewhere + UnusedBrokenConst: UnusedBrokenConst, + // Uses attr::is_used which is untracked, can't be an incremental module pass. UnusedAttributes: UnusedAttributes, From 24a0caec832d774ede930597692b291286176802 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 27 Mar 2019 05:35:18 +0900 Subject: [PATCH 32/37] librustc_driver => 2018 --- src/librustc_driver/Cargo.toml | 5 +++-- src/librustc_driver/lib.rs | 31 ++----------------------------- src/librustc_driver/pretty.rs | 32 ++++++++++++++++++-------------- 3 files changed, 23 insertions(+), 45 deletions(-) diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index a77e497af7b87..5432f80a1712c 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -2,6 +2,7 @@ authors = ["The Rust Project Developers"] name = "rustc_driver" version = "0.0.0" +edition = "2018" [lib] name = "rustc_driver" @@ -13,14 +14,14 @@ arena = { path = "../libarena" } graphviz = { path = "../libgraphviz" } log = "0.4" env_logger = { version = "0.5", default-features = false } -rustc-rayon = "0.1.2" +rayon = { version = "0.1.2", package = "rustc-rayon" } scoped-tls = "1.0" rustc = { path = "../librustc" } rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } rustc_borrowck = { path = "../librustc_borrowck" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_errors = { path = "../librustc_errors" } +errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_incremental = { path = "../librustc_incremental" } rustc_lint = { path = "../librustc_lint" } rustc_metadata = { path = "../librustc_metadata" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 25984616b878b..4b7cffaad5509 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -16,40 +16,13 @@ #![recursion_limit="256"] -extern crate arena; +#![deny(rust_2018_idioms)] + pub extern crate getopts; -extern crate graphviz; -extern crate env_logger; #[cfg(unix)] extern crate libc; -extern crate rustc_rayon as rayon; -extern crate rustc; -extern crate rustc_allocator; -extern crate rustc_target; -extern crate rustc_borrowck; -extern crate rustc_data_structures; -extern crate rustc_errors as errors; -extern crate rustc_passes; -extern crate rustc_lint; -extern crate rustc_plugin; -extern crate rustc_privacy; -extern crate rustc_incremental; -extern crate rustc_metadata; -extern crate rustc_mir; -extern crate rustc_resolve; -extern crate rustc_save_analysis; -extern crate rustc_traits; -extern crate rustc_codegen_utils; -extern crate rustc_typeck; -extern crate rustc_interface; -extern crate scoped_tls; -extern crate serialize; -extern crate smallvec; #[macro_use] extern crate log; -extern crate syntax; -extern crate syntax_ext; -extern crate syntax_pos; use pretty::{PpMode, UserIdentifiedItem}; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index ace5198deaf2e..5cefc35607db0 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -35,9 +35,9 @@ pub use self::UserIdentifiedItem::*; pub use self::PpSourceMode::*; pub use self::PpMode::*; use self::NodesMatchingUII::*; -use abort_on_err; +use crate::abort_on_err; -use source_name; +use crate::source_name; #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { @@ -191,7 +191,7 @@ impl PpSourceMode { tcx: TyCtxt<'tcx, 'tcx, 'tcx>, f: F ) -> A - where F: FnOnce(&dyn HirPrinterSupport, &hir::Crate) -> A + where F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A { match *self { PpmNormal => { @@ -296,7 +296,7 @@ impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> { impl<'hir> pprust::PpAnn for NoAnn<'hir> {} impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> { - fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) -> io::Result<()> { if let Some(tcx) = self.tcx { pprust_hir::PpAnn::nested(tcx.hir(), state, nested) @@ -322,13 +322,13 @@ impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> { } impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> { - fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { + fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> { match node { pprust::AnnNode::Expr(_) => s.popen(), _ => Ok(()), } } - fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> { match node { pprust::AnnNode::Ident(_) | pprust::AnnNode::Name(_) => Ok(()), @@ -373,7 +373,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> { } impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { - fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) -> io::Result<()> { if let Some(ref tcx) = self.tcx { pprust_hir::PpAnn::nested(tcx.hir(), state, nested) @@ -381,13 +381,13 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { Ok(()) } } - fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { + fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> { match node { pprust_hir::AnnNode::Expr(_) => s.popen(), _ => Ok(()), } } - fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> { match node { pprust_hir::AnnNode::Name(_) => Ok(()), pprust_hir::AnnNode::Item(item) => { @@ -434,7 +434,7 @@ impl<'a> PrinterSupport for HygieneAnnotation<'a> { } impl<'a> pprust::PpAnn for HygieneAnnotation<'a> { - fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> { match node { pprust::AnnNode::Ident(&ast::Ident { name, span }) => { s.s.space()?; @@ -476,7 +476,7 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { } impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { - fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) -> io::Result<()> { let old_tables = self.tables.get(); if let pprust_hir::Nested::Body(id) = nested { @@ -486,13 +486,13 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { self.tables.set(old_tables); Ok(()) } - fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { + fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> { match node { pprust_hir::AnnNode::Expr(_) => s.popen(), _ => Ok(()), } } - fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { + fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> { match node { pprust_hir::AnnNode::Expr(expr) => { s.s.space()?; @@ -580,7 +580,11 @@ impl UserIdentifiedItem { } } - fn to_one_node_id(self, user_option: &str, sess: &Session, map: &hir_map::Map) -> ast::NodeId { + fn to_one_node_id(self, + user_option: &str, + sess: &Session, + map: &hir_map::Map<'_>) + -> ast::NodeId { let fail_because = |is_wrong_because| -> ast::NodeId { let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ {}, which {}", From 8733b2ab0c6bfe60df594e41ee9b1ce1f8caeaa0 Mon Sep 17 00:00:00 2001 From: Tim Diekmann <21277928+TimDiekmann@users.noreply.github.com> Date: Wed, 27 Mar 2019 00:09:12 +0100 Subject: [PATCH 33/37] Add `Default` to `std::alloc::System` --- src/libstd/alloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index a13da2901df94..4241f47b661d7 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -130,7 +130,7 @@ pub use alloc_crate::alloc::*; /// program opts in to using jemalloc as the global allocator, `System` will /// still allocate memory using `malloc` and `HeapAlloc`. #[stable(feature = "alloc_system_type", since = "1.28.0")] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Default, Copy, Clone)] pub struct System; // The Alloc impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`. From 892f7c430dddbbd5a2e7c6146b19a762ed1e40e8 Mon Sep 17 00:00:00 2001 From: kenta7777 Date: Wed, 27 Mar 2019 10:57:03 +0900 Subject: [PATCH 34/37] renames EvalContext to InterpretCx in docs and comments. --- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc_mir/const_eval.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 9fb023156022a..0dd8316852780 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -344,7 +344,7 @@ impl<'tcx> AllocMap<'tcx> { } } - /// Returns `None` in case the `AllocId` is dangling. An `EvalContext` can still have a + /// Returns `None` in case the `AllocId` is dangling. An `InterpretCx` can still have a /// local `Allocation` for that `AllocId`, but having such an `AllocId` in a constant is /// illegal and will likely ICE. /// This function exists to allow const eval to detect the difference between evaluation- diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 211573ab49a1c..6ab89f80ef528 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -34,7 +34,7 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000; /// Should be a power of two for performance reasons. const DETECTOR_SNAPSHOT_PERIOD: isize = 256; -/// The `EvalContext` is only meant to be used to do field and index projections into constants for +/// The `InterpretCx` is only meant to be used to do field and index projections into constants for /// `simd_shuffle` and const patterns in match arms. /// /// The function containing the `match` that is currently being analyzed may have generic bounds From 14f3f6c71294fbbcb0a32286d942a4080156c6bc Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 26 Mar 2019 19:07:13 +0100 Subject: [PATCH 35/37] librustc_interface => 2018 --- src/librustc_interface/Cargo.toml | 1 + src/librustc_interface/interface.rs | 10 +++++----- src/librustc_interface/lib.rs | 27 ++------------------------- src/librustc_interface/passes.rs | 12 +++++++----- src/librustc_interface/profile/mod.rs | 3 ++- src/librustc_interface/queries.rs | 5 +++-- src/librustc_interface/util.rs | 1 + 7 files changed, 21 insertions(+), 38 deletions(-) diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 294e23dc6177c..356547db88675 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -2,6 +2,7 @@ authors = ["The Rust Project Developers"] name = "rustc_interface" version = "0.0.0" +edition = "2018" [lib] name = "rustc_interface" diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index ec6b26afb8c50..bec868be505b5 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -1,4 +1,8 @@ -use queries::Queries; +use crate::queries::Queries; +use crate::util; +use crate::profile; +pub use crate::passes::BoxedResolver; + use rustc::lint; use rustc::session::config::{self, Input}; use rustc::session::{DiagnosticOutput, Session}; @@ -15,10 +19,6 @@ use std::result; use std::sync::{Arc, Mutex}; use syntax; use syntax::source_map::{FileLoader, SourceMap}; -use util; -use profile; - -pub use passes::BoxedResolver; pub type Result = result::Result; diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs index 6a931c249b5bf..3314681b6981a 100644 --- a/src/librustc_interface/lib.rs +++ b/src/librustc_interface/lib.rs @@ -6,37 +6,14 @@ #![feature(generators)] #![cfg_attr(unix, feature(libc))] +#![deny(rust_2018_idioms)] + #![allow(unused_imports)] #![recursion_limit="256"] #[cfg(unix)] extern crate libc; -#[macro_use] -extern crate log; -extern crate rustc; -extern crate rustc_codegen_utils; -extern crate rustc_allocator; -extern crate rustc_borrowck; -extern crate rustc_incremental; -extern crate rustc_traits; -#[macro_use] -extern crate rustc_data_structures; -extern crate rustc_errors; -extern crate rustc_lint; -extern crate rustc_metadata; -extern crate rustc_mir; -extern crate rustc_passes; -extern crate rustc_plugin; -extern crate rustc_privacy; -extern crate rustc_rayon as rayon; -extern crate rustc_resolve; -extern crate rustc_typeck; -extern crate smallvec; -extern crate serialize; -extern crate syntax; -extern crate syntax_pos; -extern crate syntax_ext; pub mod interface; mod passes; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c199829b298c0..318857c3406e3 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1,7 +1,8 @@ -use interface::{Compiler, Result}; -use util; -use proc_macro_decls; +use crate::interface::{Compiler, Result}; +use crate::util; +use crate::proc_macro_decls; +use log::{debug, info, warn, log_enabled}; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::lowering::lower_crate; @@ -20,6 +21,7 @@ use rustc::session::search_paths::PathKind; use rustc_allocator as allocator; use rustc_borrowck as borrowck; use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter}; @@ -758,7 +760,7 @@ pub fn prepare_outputs( Ok(outputs) } -pub fn default_provide(providers: &mut ty::query::Providers) { +pub fn default_provide(providers: &mut ty::query::Providers<'_>) { providers.analysis = analysis; proc_macro_decls::provide(providers); plugin::build::provide(providers); @@ -783,7 +785,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) { lint::provide(providers); } -pub fn default_provide_extern(providers: &mut ty::query::Providers) { +pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { cstore::provide_extern(providers); } diff --git a/src/librustc_interface/profile/mod.rs b/src/librustc_interface/profile/mod.rs index eb13a5668f927..d0c8dff207083 100644 --- a/src/librustc_interface/profile/mod.rs +++ b/src/librustc_interface/profile/mod.rs @@ -1,8 +1,9 @@ +use log::debug; +use rustc::dep_graph::DepNode; use rustc::session::Session; use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan}; use std::sync::mpsc::{Receiver}; use std::io::{Write}; -use rustc::dep_graph::{DepNode}; use std::time::{Duration, Instant}; pub mod trace; diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 57ced0464d9fa..570509ffb2b8c 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,5 +1,6 @@ -use interface::{Compiler, Result}; -use passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo}; +use crate::interface::{Compiler, Result}; +use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo}; + use rustc_incremental::DepGraphFuture; use rustc_data_structures::sync::Lrc; use rustc::session::config::{Input, OutputFilenames, OutputType}; diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index b1ef4e315d98d..6e4f2bf24e32f 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -1,3 +1,4 @@ +use log::info; use rustc::session::config::{Input, OutputFilenames, ErrorOutputType}; use rustc::session::{self, config, early_error, filesearch, Session, DiagnosticOutput}; use rustc::session::CrateDisambiguator; From bf1068b1370f7bc3e17164cb4abd010b15073fa8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 27 Mar 2019 09:48:50 +0100 Subject: [PATCH 36/37] librustc_interface => 2018; rename rustc-rayon to rayon in Cargo.toml --- src/librustc_interface/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 356547db88675..ec934ee48212c 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["dylib"] [dependencies] log = "0.4" -rustc-rayon = "0.1.1" +rayon = { version = "0.1.1", package = "rustc-rayon" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } scoped-tls = "1.0" syntax = { path = "../libsyntax" } From 2368aa8e97e9f3d3df1a75dc798e0e3f4cced7da Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Wed, 27 Mar 2019 19:30:33 +0900 Subject: [PATCH 37/37] Add some tests --- .../existential-types-with-cycle-error.rs | 12 ++++++++ .../existential-types-with-cycle-error.stderr | 30 +++++++++++++++++++ .../existential-types-with-cycle-error2.rs | 16 ++++++++++ ...existential-types-with-cycle-error2.stderr | 30 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 src/test/ui/existential_types/existential-types-with-cycle-error.rs create mode 100644 src/test/ui/existential_types/existential-types-with-cycle-error.stderr create mode 100644 src/test/ui/existential_types/existential-types-with-cycle-error2.rs create mode 100644 src/test/ui/existential_types/existential-types-with-cycle-error2.stderr diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error.rs b/src/test/ui/existential_types/existential-types-with-cycle-error.rs new file mode 100644 index 0000000000000..3f0190892ebb3 --- /dev/null +++ b/src/test/ui/existential_types/existential-types-with-cycle-error.rs @@ -0,0 +1,12 @@ +#![feature(existential_type)] + +existential type Foo: Fn() -> Foo; +//~^ ERROR: cycle detected when processing `Foo` + +fn crash(x: Foo) -> Foo { + x +} + +fn main() { + +} diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error.stderr b/src/test/ui/existential_types/existential-types-with-cycle-error.stderr new file mode 100644 index 0000000000000..56057a9caa4a5 --- /dev/null +++ b/src/test/ui/existential_types/existential-types-with-cycle-error.stderr @@ -0,0 +1,30 @@ +error[E0391]: cycle detected when processing `Foo` + --> $DIR/existential-types-with-cycle-error.rs:3:1 + | +LL | existential type Foo: Fn() -> Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires processing `crash`... + --> $DIR/existential-types-with-cycle-error.rs:6:25 + | +LL | fn crash(x: Foo) -> Foo { + | _________________________^ +LL | | x +LL | | } + | |_^ + = note: ...which again requires processing `Foo`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/existential-types-with-cycle-error.rs:1:1 + | +LL | / #![feature(existential_type)] +LL | | +LL | | existential type Foo: Fn() -> Foo; +LL | | +... | +LL | | +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error2.rs b/src/test/ui/existential_types/existential-types-with-cycle-error2.rs new file mode 100644 index 0000000000000..29410309ef26e --- /dev/null +++ b/src/test/ui/existential_types/existential-types-with-cycle-error2.rs @@ -0,0 +1,16 @@ +#![feature(existential_type)] + +pub trait Bar { + type Item; +} + +existential type Foo: Bar; +//~^ ERROR: cycle detected when processing `Foo` + +fn crash(x: Foo) -> Foo { + x +} + +fn main() { + +} diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr b/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr new file mode 100644 index 0000000000000..8c7bf52470ab2 --- /dev/null +++ b/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr @@ -0,0 +1,30 @@ +error[E0391]: cycle detected when processing `Foo` + --> $DIR/existential-types-with-cycle-error2.rs:7:1 + | +LL | existential type Foo: Bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires processing `crash`... + --> $DIR/existential-types-with-cycle-error2.rs:10:25 + | +LL | fn crash(x: Foo) -> Foo { + | _________________________^ +LL | | x +LL | | } + | |_^ + = note: ...which again requires processing `Foo`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/existential-types-with-cycle-error2.rs:1:1 + | +LL | / #![feature(existential_type)] +LL | | +LL | | pub trait Bar { +LL | | type Item; +... | +LL | | +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`.