From: Mazdak Farrokhzad Date: Wed, 8 May 2019 22:58:28 +0000 (+0200) Subject: Rollup merge of #60627 - matklad:test, r=estebank X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=d20b6927569a308baf41ad58b854775961b49bf7;hp=c87d2ccf88f1b9ca039d18530fd474e5ad868bc4;p=rust.git Rollup merge of #60627 - matklad:test, r=estebank test for #50518 It was fixed somewhere between 1.28.0 and 1.31.1 closes #50518 r? @estebank Where's the best place to add this test? I *think* we want "compile-pass" for this test (no need to run a binary, and not running saves us a millisecond of process creation) , but there's no compile-pass anymore. Should this be UI test with empty stdout, stderr and zero return code? --- diff --git a/Cargo.lock b/Cargo.lock index c930b628f4b..0154b96751d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -115,7 +115,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -271,9 +271,10 @@ dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opener 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -449,7 +450,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -735,7 +736,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -901,7 +902,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1062,7 +1063,7 @@ name = "hashbrown" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-alloc 1.0.0", "rustc-std-workspace-core 1.0.0", ] @@ -1688,11 +1689,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "opener" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1765,7 +1764,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1775,7 +1774,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -1960,7 +1959,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2485,7 +2484,7 @@ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2613,7 +2612,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2843,7 +2842,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2905,7 +2904,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3022,7 +3021,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3291,7 +3290,7 @@ dependencies = [ "alloc 0.0.0", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3883,7 +3882,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4079,7 +4078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4ada53ac629568219809178f988ca2aac9889e9a847379588c097d30ce185145" +"checksum compiler_builtins 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6549720ae78db799196d4af8f719facb4c7946710b4b64148482553e54b56d15" "checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" @@ -4202,7 +4201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum opener 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "04b1d6b086d9b3009550f9b6f81b10ad9428cf14f404b8e1a3a06f6f012c8ec9" +"checksum opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "998c59e83d9474c01127a96e023b7a04bb061dd286bf8bb939d31dc8d31a7448" "checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)" = "26bb632127731bf4ac49bf86a5dde12d2ca0918c2234fc39d79d4da2ccbc6da7" diff --git a/appveyor.yml b/appveyor.yml index be960dc13af..dffd79c56e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -158,9 +158,9 @@ install: # Note that the LLVM installer is an NSIS installer # # Original downloaded here came from - # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe - - if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe - - if NOT defined MINGW_URL .\LLVM-7.0.0-win64.exe /S /NCRC /D=C:\clang-rust + # http://releases.llvm.org/8.0.0/LLVM-8.0.0-win64.exe + - if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-8.0.0-win64.exe + - if NOT defined MINGW_URL .\LLVM-8.0.0-win64.exe /S /NCRC /D=C:\clang-rust - if NOT defined MINGW_URL set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=C:\clang-rust\bin\clang-cl.exe # Here we do a pretty heinous thing which is to mangle the MinGW installation diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index eb673488170..2edd946ff11 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -87,7 +87,6 @@ #![feature(fundamental)] #![feature(lang_items)] #![feature(libc)] -#![feature(needs_allocator)] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(pattern)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 5bd442bc066..9fb071d2952 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -665,8 +665,8 @@ pub fn swap(x: &mut T, y: &mut T) { /// let mut v: Vec = vec![1, 2]; /// /// let old_v = mem::replace(&mut v, vec![3, 4, 5]); -/// assert_eq!(2, old_v.len()); -/// assert_eq!(3, v.len()); +/// assert_eq!(vec![1, 2], old_v); +/// assert_eq!(vec![3, 4, 5], v); /// ``` /// /// `replace` allows consumption of a struct field by replacing it with another value. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c1887a93490..562a7a4b3c7 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -214,11 +214,31 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { mod wrapping; +macro_rules! usize_isize_to_xe_bytes_doc { + () => {" + +**Note**: This function returns an array of length 2, 4 or 8 bytes +depending on the target pointer size. + +"} +} + + +macro_rules! usize_isize_from_xe_bytes_doc { + () => {" + +**Note**: This function takes an array of length 2, 4 or 8 bytes +depending on the target pointer size. + +"} +} + // `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, - $reversed:expr, $le_bytes:expr, $be_bytes:expr) => { + $reversed:expr, $le_bytes:expr, $be_bytes:expr, + $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { doc_comment! { concat!("Returns the smallest value that can be represented by this integer type. @@ -2023,7 +2043,9 @@ pub const fn is_negative(self) -> bool { self < 0 } doc_comment! { concat!("Return the memory representation of this integer as a byte array in big-endian (network) byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -2041,7 +2063,9 @@ pub const fn is_negative(self) -> bool { self < 0 } doc_comment! { concat!("Return the memory representation of this integer as a byte array in little-endian byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -2064,7 +2088,9 @@ pub const fn is_negative(self) -> bool { self < 0 } As the target platform's native endianness is used, portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. - +", +$to_xe_bytes_doc, +" [`to_be_bytes`]: #method.to_be_bytes [`to_le_bytes`]: #method.to_le_bytes @@ -2089,7 +2115,9 @@ pub const fn is_negative(self) -> bool { self < 0 } doc_comment! { concat!("Create an integer value from its representation as a byte array in big endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -2120,7 +2148,9 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), concat!(" Create an integer value from its representation as a byte array in little endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -2157,7 +2187,9 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), [`from_be_bytes`]: #method.from_be_bytes [`from_le_bytes`]: #method.from_le_bytes - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -2193,20 +2225,20 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[lang = "i8"] impl i8 { int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", - "[0x12]", "[0x12]" } + "[0x12]", "[0x12]", "", "" } } #[lang = "i16"] impl i16 { int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", - "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]" } + "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "i32"] impl i32 { int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]" } + "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "i64"] @@ -2214,7 +2246,7 @@ impl i64 { int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } } #[lang = "i128"] @@ -2226,14 +2258,15 @@ impl i128 { "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]" } + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" } } #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { int_impl! { isize, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", - "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]" } + "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] @@ -2241,7 +2274,8 @@ impl isize { impl isize { int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]" } + "[0x12, 0x34, 0x56, 0x78]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "64")] @@ -2250,14 +2284,16 @@ impl isize { int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } // `Int` + `UnsignedInt` implemented for unsigned integers macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, - $reversed:expr, $le_bytes:expr, $be_bytes:expr) => { + $reversed:expr, $le_bytes:expr, $be_bytes:expr, + $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { doc_comment! { concat!("Returns the smallest value that can be represented by this integer type. @@ -3817,7 +3853,9 @@ pub fn wrapping_next_power_of_two(self) -> Self { doc_comment! { concat!("Return the memory representation of this integer as a byte array in big-endian (network) byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -3835,7 +3873,9 @@ pub fn wrapping_next_power_of_two(self) -> Self { doc_comment! { concat!("Return the memory representation of this integer as a byte array in little-endian byte order. - +", +$to_xe_bytes_doc, +" # Examples ``` @@ -3858,7 +3898,9 @@ pub fn wrapping_next_power_of_two(self) -> Self { As the target platform's native endianness is used, portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. - +", +$to_xe_bytes_doc, +" [`to_be_bytes`]: #method.to_be_bytes [`to_le_bytes`]: #method.to_le_bytes @@ -3883,7 +3925,9 @@ pub fn wrapping_next_power_of_two(self) -> Self { doc_comment! { concat!("Create an integer value from its representation as a byte array in big endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -3914,7 +3958,9 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), concat!(" Create an integer value from its representation as a byte array in little endian. - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -3951,7 +3997,9 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), [`from_be_bytes`]: #method.from_be_bytes [`from_le_bytes`]: #method.from_le_bytes - +", +$from_xe_bytes_doc, +" # Examples ``` @@ -3987,7 +4035,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[lang = "u8"] impl u8 { uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", - "[0x12]" } + "[0x12]", "", "" } /// Checks if the value is within the ASCII range. @@ -4506,13 +4554,13 @@ pub fn is_ascii_control(&self) -> bool { #[lang = "u16"] impl u16 { uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]" } + "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "u32"] impl u32 { uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]" } + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "u64"] @@ -4520,7 +4568,8 @@ impl u64 { uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + "", ""} } #[lang = "u128"] @@ -4531,20 +4580,23 @@ impl u128 { "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]" } + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + "", ""} } #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]" } + "[0x34, 0x12]", "[0x12, 0x34]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]" } + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "64")] @@ -4553,7 +4605,8 @@ impl usize { uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" } + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } /// A classification of floating point numbers. diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index ff52a03d9dd..331edb73d6d 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -44,6 +44,19 @@ fn main() { cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); } + // Assume that the Unixes we are building this for have fnctl() available + if env::var_os("CARGO_CFG_UNIX").is_some() { + cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1")); + } + + // This should be a pretty good heuristic for when to set + // COMPILER_RT_HAS_ATOMICS + if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC").map(|features| { + features.to_string_lossy().to_lowercase().contains("cas") + }).unwrap_or(false) { + cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); + } + // The source for `compiler-rt` comes from the `compiler-builtins` crate, so // load our env var set by cargo to find the source code. let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 1ecc580d8c5..a87c98a04a4 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -1021,25 +1021,22 @@ fn complete_task( fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { debug_assert!(!kind.is_eval_always()); - let mut fingerprint = self.anon_id_seed; let mut hasher = StableHasher::new(); - for &read in task_deps.reads.iter() { - let read_dep_node = self.data[read].node; + // The dep node indices are hashed here instead of hashing the dep nodes of the + // dependencies. These indices may refer to different nodes per session, but this isn't + // a problem here because we that ensure the final dep node hash is per session only by + // combining it with the per session random number `anon_id_seed`. This hash only need + // to map the dependencies to a single value on a per session basis. + task_deps.reads.hash(&mut hasher); - ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher); + let target_dep_node = DepNode { + kind, // Fingerprint::combine() is faster than sending Fingerprint // through the StableHasher (at least as long as StableHasher // is so slow). - fingerprint = fingerprint.combine(read_dep_node.hash); - } - - fingerprint = fingerprint.combine(hasher.finish()); - - let target_dep_node = DepNode { - kind, - hash: fingerprint, + hash: self.anon_id_seed.combine(hasher.finish()), }; self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO).0 diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index fd089fc688e..a1bfd417566 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2205,4 +2205,6 @@ trait Foo { } E0711, // a feature has been declared with conflicting stability attributes // E0702, // replaced with a generic attribute input check E0726, // non-explicit (not `'_`) elided lifetime in unsupported position + E0727, // `async` generators are not yet supported + E0728, // `await` must be in an `async` function or block } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 36e4195c989..20e016b8b5b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -95,6 +95,7 @@ pub struct LoweringContext<'a> { modules: BTreeMap, is_generator: bool, + is_async_body: bool, catch_scopes: Vec, loop_scopes: Vec, @@ -248,6 +249,7 @@ pub fn lower_crate( item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), is_generator: false, + is_async_body: false, is_in_trait_impl: false, lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, @@ -801,8 +803,17 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hi } fn record_body(&mut self, value: hir::Expr, arguments: HirVec) -> hir::BodyId { + if self.is_generator && self.is_async_body { + span_err!( + self.sess, + value.span, + E0727, + "`async` generators are not yet supported", + ); + self.sess.abort_if_errors(); + } let body = hir::Body { - is_generator: self.is_generator, + is_generator: self.is_generator || self.is_async_body, arguments, value, }; @@ -1124,7 +1135,8 @@ fn make_async_expr( span: Span, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { - let prev_is_generator = mem::replace(&mut self.is_generator, true); + let prev_is_generator = mem::replace(&mut self.is_generator, false); + let prev_is_async_body = mem::replace(&mut self.is_async_body, true); let output = match ret_ty { Some(ty) => FunctionRetTy::Ty(P(ty.clone())), None => FunctionRetTy::Default(span), @@ -1140,6 +1152,7 @@ fn make_async_expr( let body_expr = body(self); let body_id = self.record_body(body_expr, arguments); self.is_generator = prev_is_generator; + self.is_async_body = prev_is_async_body; let capture_clause = self.lower_capture_clause(capture_clause); let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None); @@ -1167,11 +1180,13 @@ fn lower_body(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId where F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr, { - let prev = mem::replace(&mut self.is_generator, false); + let prev_generator = mem::replace(&mut self.is_generator, false); + let prev_async = mem::replace(&mut self.is_async_body, false); let arguments = self.lower_args(decl); let result = f(self); let r = self.record_body(result, arguments); - self.is_generator = prev; + self.is_generator = prev_generator; + self.is_async_body = prev_async; return r; } @@ -4205,6 +4220,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { }) }) } + ExprKind::Await(_origin, ref expr) => self.lower_await(e.span, expr), ExprKind::Closure( capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span ) => { @@ -4326,12 +4342,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { let id = self.next_id(); let e1 = self.lower_expr(e1); let e2 = self.lower_expr(e2); - let ty_path = P(self.std_path(e.span, &["ops", "RangeInclusive"], None, false)); - let ty = P(self.ty_path(id, e.span, hir::QPath::Resolved(None, ty_path))); - let new_seg = P(hir::PathSegment::from_ident(Ident::from_str("new"))); - let new_path = hir::QPath::TypeRelative(ty, new_seg); - let new = P(self.expr(e.span, hir::ExprKind::Path(new_path), ThinVec::new())); - hir::ExprKind::Call(new, hir_vec![e1, e2]) + self.expr_call_std_assoc_fn( + id, + e.span, + &["ops", "RangeInclusive"], + "new", + hir_vec![e1, e2], + ) } ExprKind::Range(ref e1, ref e2, lims) => { use syntax::ast::RangeLimits::*; @@ -4468,9 +4485,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { let expr = opt_expr .as_ref() .map(|x| self.lower_expr(x)) - .unwrap_or_else(|| - self.expr(e.span, hir::ExprKind::Tup(hir_vec![]), ThinVec::new()) - ); + .unwrap_or_else(|| self.expr_unit(e.span)); hir::ExprKind::Yield(P(expr)) } @@ -4503,7 +4518,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { let body = if let Some(else_expr) = wildcard_arm { P(self.lower_expr(else_expr)) } else { - self.expr_tuple(e.span, hir_vec![]) + P(self.expr_tuple(e.span, hir_vec![])) }; arms.push(self.arm(hir_vec![wildcard_pattern], body)); } @@ -4651,8 +4666,11 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid)); let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter); let next_path = &["iter", "Iterator", "next"]; - let next_path = P(self.expr_std_path(head_sp, next_path, None, ThinVec::new())); - let next_expr = P(self.expr_call(head_sp, next_path, hir_vec![ref_mut_iter])); + let next_expr = P(self.expr_call_std_path( + head_sp, + next_path, + hir_vec![ref_mut_iter], + )); let arms = hir_vec![pat_arm, break_arm]; P(self.expr( @@ -4723,9 +4741,11 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { let into_iter_path = &["iter", "IntoIterator", "into_iter"]; - let into_iter = P(self.expr_std_path( - head_sp, into_iter_path, None, ThinVec::new())); - P(self.expr_call(head_sp, into_iter, hir_vec![head])) + P(self.expr_call_std_path( + head_sp, + into_iter_path, + hir_vec![head], + )) }; let match_expr = P(self.expr_match( @@ -4778,9 +4798,11 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { let sub_expr = self.lower_expr(sub_expr); let path = &["ops", "Try", "into_result"]; - let path = P(self.expr_std_path( - unstable_span, path, None, ThinVec::new())); - P(self.expr_call(e.span, path, hir_vec![sub_expr])) + P(self.expr_call_std_path( + unstable_span, + path, + hir_vec![sub_expr], + )) }; // `#[allow(unreachable_code)]` @@ -4817,12 +4839,9 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { let err_ident = self.str_to_ident("err"); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { - let path = &["convert", "From", "from"]; - let from = P(self.expr_std_path( - try_span, path, None, ThinVec::new())); + let from_path = &["convert", "From", "from"]; let err_expr = self.expr_ident(try_span, err_ident, err_local_nid); - - self.expr_call(try_span, from, hir_vec![err_expr]) + self.expr_call_std_path(try_span, from_path, hir_vec![err_expr]) }; let from_err_expr = self.wrap_in_try_constructor("from_error", from_expr, unstable_span); @@ -5056,6 +5075,42 @@ fn expr_call( self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new()) } + // Note: associated functions must use `expr_call_std_path`. + fn expr_call_std_path( + &mut self, + span: Span, + path_components: &[&str], + args: hir::HirVec, + ) -> hir::Expr { + let path = P(self.expr_std_path(span, path_components, None, ThinVec::new())); + self.expr_call(span, path, args) + } + + // Create an expression calling an associated function of an std type. + // + // Associated functions cannot be resolved through the normal `std_path` function, + // as they are resolved differently and so cannot use `expr_call_std_path`. + // + // This function accepts the path component (`ty_path_components`) separately from + // the name of the associated function (`assoc_fn_name`) in order to facilitate + // separate resolution of the type and creation of a path referring to its associated + // function. + fn expr_call_std_assoc_fn( + &mut self, + ty_path_id: hir::HirId, + span: Span, + ty_path_components: &[&str], + assoc_fn_name: &str, + args: hir::HirVec, + ) -> hir::ExprKind { + let ty_path = P(self.std_path(span, ty_path_components, None, false)); + let ty = P(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path))); + let fn_seg = P(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name))); + let fn_path = hir::QPath::TypeRelative(ty, fn_seg); + let fn_expr = P(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); + hir::ExprKind::Call(fn_expr, args) + } + fn expr_ident(&mut self, span: Span, ident: Ident, binding: hir::HirId) -> hir::Expr { self.expr_ident_with_attrs(span, ident, binding, ThinVec::new()) } @@ -5127,8 +5182,12 @@ fn expr_block(&mut self, b: P, attrs: ThinVec) -> hir::Ex self.expr(b.span, hir::ExprKind::Block(b, None), attrs) } - fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec) -> P { - P(self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new())) + fn expr_unit(&mut self, sp: Span) -> hir::Expr { + self.expr_tuple(sp, hir_vec![]) + } + + fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec) -> hir::Expr { + self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new()) } fn expr(&mut self, span: Span, node: hir::ExprKind, attrs: ThinVec) -> hir::Expr { @@ -5184,6 +5243,23 @@ fn block_all( } } + fn expr_unsafe(&mut self, expr: P) -> hir::Expr { + let hir_id = self.next_id(); + let span = expr.span; + self.expr( + span, + hir::ExprKind::Block(P(hir::Block { + stmts: hir_vec![], + expr: Some(expr), + hir_id, + rules: hir::UnsafeBlock(hir::CompilerGenerated), + span, + targeted_by_break: false, + }), None), + ThinVec::new(), + ) + } + fn pat_ok(&mut self, span: Span, pat: P) -> P { self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat]) } @@ -5258,13 +5334,12 @@ fn std_path( span: Span, components: &[&str], params: Option>, - is_value: bool + is_value: bool, ) -> hir::Path { let mut path = self.resolver .resolve_str_path(span, self.crate_root, components, is_value); path.segments.last_mut().unwrap().args = params; - for seg in path.segments.iter_mut() { if seg.hir_id.is_some() { seg.hir_id = Some(self.next_id()); @@ -5465,6 +5540,175 @@ fn wrap_in_try_constructor( ThinVec::new())); P(self.expr_call(e.span, from_err, hir_vec![e])) } + + fn lower_await( + &mut self, + await_span: Span, + expr: &ast::Expr, + ) -> hir::ExprKind { + // to: + // + // { + // let mut pinned = ; + // loop { + // match ::std::future::poll_with_tls_context(unsafe { + // ::std::pin::Pin::new_unchecked(&mut pinned) + // }) { + // ::std::task::Poll::Ready(x) => break x, + // ::std::task::Poll::Pending => {}, + // } + // yield (); + // } + // } + if !self.is_async_body { + span_err!( + self.sess, + await_span, + E0728, + "`await` is only allowed inside `async` functions and blocks" + ); + self.sess.abort_if_errors(); + } + let span = self.mark_span_with_reason( + CompilerDesugaringKind::Await, + await_span, + None, + ); + let gen_future_span = self.mark_span_with_reason( + CompilerDesugaringKind::Await, + await_span, + Some(vec![Symbol::intern("gen_future")].into()), + ); + + // let mut pinned = ; + let expr = P(self.lower_expr(expr)); + let pinned_ident = self.str_to_ident("pinned"); + let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode( + span, + pinned_ident, + hir::BindingAnnotation::Mutable, + ); + let pinned_let = self.stmt_let_pat( + span, + Some(expr), + pinned_pat, + hir::LocalSource::AwaitDesugar, + ); + + // ::std::future::poll_with_tls_context(unsafe { + // ::std::pin::Pin::new_unchecked(&mut pinned) + // })` + let poll_expr = { + let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid)); + let ref_mut_pinned = self.expr_mut_addr_of(span, pinned); + let pin_ty_id = self.next_id(); + let new_unchecked_expr_kind = self.expr_call_std_assoc_fn( + pin_ty_id, + span, + &["pin", "Pin"], + "new_unchecked", + hir_vec![ref_mut_pinned], + ); + let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new())); + let unsafe_expr = self.expr_unsafe(new_unchecked); + P(self.expr_call_std_path( + gen_future_span, + &["future", "poll_with_tls_context"], + hir_vec![unsafe_expr], + )) + }; + + // `::std::task::Poll::Ready(x) => break x` + let loop_node_id = self.sess.next_node_id(); + let loop_hir_id = self.lower_node_id(loop_node_id); + let ready_arm = { + let x_ident = self.str_to_ident("x"); + let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); + let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); + let ready_pat = self.pat_std_enum( + span, + &["task", "Poll", "Ready"], + hir_vec![x_pat], + ); + let break_x = self.with_loop_scope(loop_node_id, |this| { + let expr_break = hir::ExprKind::Break( + this.lower_loop_destination(None), + Some(x_expr), + ); + P(this.expr(await_span, expr_break, ThinVec::new())) + }); + self.arm(hir_vec![ready_pat], break_x) + }; + + // `::std::task::Poll::Pending => {}` + let pending_arm = { + let pending_pat = self.pat_std_enum( + span, + &["task", "Poll", "Pending"], + hir_vec![], + ); + let empty_block = P(hir::Block { + stmts: hir_vec![], + expr: None, + hir_id: self.next_id(), + rules: hir::DefaultBlock, + span, + targeted_by_break: false, + }); + let empty_block = P(self.expr_block(empty_block, ThinVec::new())); + self.arm(hir_vec![pending_pat], empty_block) + }; + + let match_stmt = { + let match_expr = P(self.expr_match( + span, + poll_expr, + hir_vec![ready_arm, pending_arm], + hir::MatchSource::AwaitDesugar, + )); + hir::Stmt { + hir_id: self.next_id(), + node: hir::StmtKind::Expr(match_expr), + span, + } + }; + + let yield_stmt = { + let unit = self.expr_unit(span); + let yield_expr = P(self.expr( + span, + hir::ExprKind::Yield(P(unit)), + ThinVec::new(), + )); + hir::Stmt { + hir_id: self.next_id(), + node: hir::StmtKind::Expr(yield_expr), + span, + } + }; + + let loop_block = P(self.block_all( + span, + hir_vec![match_stmt, yield_stmt], + None, + )); + + let loop_expr = P(hir::Expr { + hir_id: loop_hir_id, + node: hir::ExprKind::Loop( + loop_block, + None, + hir::LoopSource::Loop, + ), + span, + attrs: ThinVec::new(), + }); + + hir::ExprKind::Block( + P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))), + None, + ) + } } fn body_ids(bodies: &BTreeMap) -> Vec { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 50bd89a1589..136d683e76b 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,9 +1,11 @@ use super::*; use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex}; use crate::hir; +use crate::hir::map::HirEntryMap; use crate::hir::def_id::{LOCAL_CRATE, CrateNum}; use crate::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc_data_structures::svh::Svh; +use rustc_data_structures::indexed_vec::IndexVec; use crate::ich::Fingerprint; use crate::middle::cstore::CrateStore; use crate::session::CrateDisambiguator; @@ -12,6 +14,7 @@ use syntax::ast::NodeId; use syntax::source_map::SourceMap; use syntax_pos::Span; +use std::iter::repeat; use crate::ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -25,7 +28,7 @@ pub(super) struct NodeCollector<'a, 'hir> { source_map: &'a SourceMap, /// The node map - map: FxHashMap>, + map: HirEntryMap<'hir>, /// The parent of this node parent_node: hir::HirId, @@ -142,11 +145,15 @@ pub(super) fn root(sess: &'a Session, ); } + let (lo, hi) = definitions.def_index_counts_lo_hi(); + let mut collector = NodeCollector { krate, source_map: sess.source_map(), - map: FxHashMap::with_capacity_and_hasher(sess.current_node_id_count(), - Default::default()), + map: [ + repeat(None).take(lo).collect(), + repeat(None).take(hi).collect(), + ], parent_node: hir::CRATE_HIR_ID, current_signature_dep_index: root_mod_sig_dep_index, current_full_dep_index: root_mod_full_dep_index, @@ -171,7 +178,7 @@ pub(super) fn finalize_and_compute_crate_hash(mut self, crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64) - -> (FxHashMap>, Svh) + -> (HirEntryMap<'hir>, Svh) { self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); @@ -224,7 +231,17 @@ pub(super) fn finalize_and_compute_crate_hash(mut self, fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { debug!("hir_map: {:?} => {:?}", id, entry); - self.map.insert(id, entry); + let local_map = &mut self.map[id.owner.address_space().index()][id.owner.as_array_index()]; + let i = id.local_id.as_u32() as usize; + if local_map.is_none() { + *local_map = Some(IndexVec::with_capacity(i + 1)); + } + let local_map = local_map.as_mut().unwrap(); + let len = local_map.len(); + if i >= len { + local_map.extend(repeat(None).take(i - len + 1)); + } + local_map[id.local_id] = Some(entry); } fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a59170e9666..c2b513a39a8 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -11,6 +11,7 @@ use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; +use rustc_data_structures::indexed_vec::IndexVec; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; use syntax::ext::base::MacroKind; @@ -161,6 +162,13 @@ pub fn untracked_krate<'hir>(&'hir self) -> &'hir Crate { } } +/// This type is effectively a `HashMap>`, +/// but is implemented by 3 layers of arrays. +/// - the outer layer is `[A; 2]` and correspond to the 2 address spaces `DefIndex`es can be in +/// - then we have `A = Vec>` mapping a `DefIndex`'s index to a inner value +/// - which is `B = IndexVec>` which finally gives you the `Entry`. +pub(super) type HirEntryMap<'hir> = [Vec>>>>; 2]; + /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. #[derive(Clone)] pub struct Map<'hir> { @@ -174,7 +182,7 @@ pub struct Map<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - map: FxHashMap>, + map: HirEntryMap<'hir>, definitions: &'hir Definitions, @@ -183,6 +191,12 @@ pub struct Map<'hir> { } impl<'hir> Map<'hir> { + #[inline] + fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { + let local_map = self.map[id.owner.address_space().index()].get(id.owner.as_array_index())?; + local_map.as_ref()?.get(id.local_id)?.as_ref() + } + /// Registers a read in the dependency graph of the AST node with /// the given `id`. This needs to be called each time a public /// function returns the HIR for a node -- in other words, when it @@ -191,7 +205,7 @@ impl<'hir> Map<'hir> { /// read recorded). If the function just returns a DefId or /// NodeId, no actual content was returned, so no read is needed. pub fn read(&self, hir_id: HirId) { - if let Some(entry) = self.map.get(&hir_id) { + if let Some(entry) = self.lookup(hir_id) { self.dep_graph.read_index(entry.dep_node); } else { bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id) @@ -378,12 +392,8 @@ fn def_kind(&self, node_id: NodeId) -> Option { }) } - fn entry_count(&self) -> usize { - self.map.len() - } - fn find_entry(&self, id: HirId) -> Option> { - self.map.get(&id).cloned() + self.lookup(id).cloned() } pub fn krate(&self) -> &'hir Crate { @@ -433,7 +443,7 @@ pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> NodeId { let parent = self.get_parent_node_by_hir_id(hir_id); - assert!(self.map.get(&parent).map_or(false, |e| e.is_body_owner(hir_id))); + assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id))); self.hir_to_node_id(parent) } @@ -1004,6 +1014,34 @@ pub fn attrs_by_hir_id(&self, id: HirId) -> &'hir [ast::Attribute] { attrs.unwrap_or(&[]) } + /// Returns an iterator that yields all the hir ids in the map. + fn all_ids<'a>(&'a self) -> impl Iterator + 'a { + // This code is a bit awkward because the map is implemented as 3 levels of arrays, + // see the comment on `HirEntryMap`. + let map = &self.map; + + // Look at both the def index address spaces + let spaces = [DefIndexAddressSpace::Low, DefIndexAddressSpace::High].iter().cloned(); + spaces.flat_map(move |space| { + // Iterate over all the indices in the address space and return a reference to + // local maps and their index given that they exist. + let local_maps = map[space.index()].iter().enumerate().filter_map(|(i, local_map)| { + local_map.as_ref().map(|m| (i, m)) + }); + + local_maps.flat_map(move |(array_index, local_map)| { + // Iterate over each valid entry in the local map + local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { + // Reconstruct the HirId based on the 3 indices we used to find it + HirId { + owner: DefIndex::from_array_index(array_index, space), + local_id: i, + } + })) + }) + }) + } + /// Returns an iterator that yields the node id's with paths that /// match `parts`. (Requires `parts` is non-empty.) /// @@ -1012,13 +1050,16 @@ pub fn attrs_by_hir_id(&self, id: HirId) -> &'hir [ast::Attribute] { /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) - -> NodesMatchingSuffix<'a, 'hir> { - NodesMatchingSuffix { + -> impl Iterator + 'a { + let nodes = NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), in_which: &parts[..parts.len() - 1], - idx: ast::CRATE_NODE_ID, - } + }; + + self.all_ids().filter(move |hir| nodes.matces_suffix(*hir)).map(move |hir| { + self.hir_to_node_id(hir) + }) } pub fn span(&self, id: NodeId) -> Span { @@ -1097,21 +1138,20 @@ pub fn hir_to_pretty_string(&self, id: HirId) -> String { } } -pub struct NodesMatchingSuffix<'a, 'hir:'a> { - map: &'a Map<'hir>, +pub struct NodesMatchingSuffix<'a> { + map: &'a Map<'a>, item_name: &'a String, in_which: &'a [String], - idx: NodeId, } -impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { +impl<'a> NodesMatchingSuffix<'a> { /// Returns `true` only if some suffix of the module path for parent /// matches `self.in_which`. /// /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; /// returns true if parent's path ends with the suffix /// `x_0::x_1::...::x_k`. - fn suffix_matches(&self, parent: NodeId) -> bool { + fn suffix_matches(&self, parent: HirId) -> bool { let mut cursor = parent; for part in self.in_which.iter().rev() { let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { @@ -1121,7 +1161,7 @@ fn suffix_matches(&self, parent: NodeId) -> bool { if mod_name != &**part { return false; } - cursor = self.map.get_parent(mod_id); + cursor = self.map.get_parent_item(mod_id); } return true; @@ -1131,14 +1171,14 @@ fn suffix_matches(&self, parent: NodeId) -> bool { // If `id` itself is a mod named `m` with parent `p`, then // returns `Some(id, m, p)`. If `id` has no mod in its parent // chain, then returns `None`. - fn find_first_mod_parent<'a>(map: &'a Map<'_>, mut id: NodeId) -> Option<(NodeId, Name)> { + fn find_first_mod_parent<'a>(map: &'a Map<'_>, mut id: HirId) -> Option<(HirId, Name)> { loop { - if let Node::Item(item) = map.find(id)? { + if let Node::Item(item) = map.find_by_hir_id(id)? { if item_is_mod(&item) { return Some((id, item.ident.name)) } } - let parent = map.get_parent(id); + let parent = map.get_parent_item(id); if parent == id { return None } id = parent; } @@ -1154,35 +1194,21 @@ fn item_is_mod(item: &Item) -> bool { // We are looking at some node `n` with a given name and parent // id; do their names match what I am seeking? - fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { + fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool { name == &**self.item_name && self.suffix_matches(parent_of_n) } -} -impl<'a, 'hir> Iterator for NodesMatchingSuffix<'a, 'hir> { - type Item = NodeId; - - fn next(&mut self) -> Option { - loop { - let idx = self.idx; - if idx.as_usize() >= self.map.entry_count() { - return None; - } - self.idx = NodeId::from_u32(self.idx.as_u32() + 1); - let hir_idx = self.map.node_to_hir_id(idx); - let name = match self.map.find_entry(hir_idx).map(|entry| entry.node) { - Some(Node::Item(n)) => n.name(), - Some(Node::ForeignItem(n)) => n.name(), - Some(Node::TraitItem(n)) => n.name(), - Some(Node::ImplItem(n)) => n.name(), - Some(Node::Variant(n)) => n.name(), - Some(Node::Field(n)) => n.name(), - _ => continue, - }; - if self.matches_names(self.map.get_parent(idx), name) { - return Some(idx) - } - } + fn matces_suffix(&self, hir: HirId) -> bool { + let name = match self.map.find_entry(hir).map(|entry| entry.node) { + Some(Node::Item(n)) => n.name(), + Some(Node::ForeignItem(n)) => n.name(), + Some(Node::TraitItem(n)) => n.name(), + Some(Node::ImplItem(n)) => n.name(), + Some(Node::Variant(n)) => n.name(), + Some(Node::Field(n)) => n.name(), + _ => return false, + }; + self.matches_names(self.map.get_parent_item(hir), name) } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1e357e13417..01de7917e6e 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1606,6 +1606,8 @@ pub enum LocalSource { /// } /// ``` AsyncFn, + /// A desugared `.await`. + AwaitDesugar, } /// Hints at the original code for a `match _ { .. }`. @@ -1624,6 +1626,8 @@ pub enum MatchSource { ForLoopDesugar, /// A desugared `?` operator. TryDesugar, + /// A desugared `.await`. + AwaitDesugar, } /// The loop type that yielded an `ExprKind::Loop`. diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 40cce8e77c0..90dd5099cbf 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -396,6 +396,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>( impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind { Async, + Await, QuestionMark, ExistentialReturnType, ForLoop, diff --git a/src/librustc/infer/at.rs b/src/librustc/infer/at.rs index 34cd3ae5427..57721108892 100644 --- a/src/librustc/infer/at.rs +++ b/src/librustc/infer/at.rs @@ -27,6 +27,7 @@ use super::*; +use crate::ty::Const; use crate::ty::relate::{Relate, TypeRelation}; pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> { @@ -308,6 +309,20 @@ fn to_trace(cause: &ObligationCause<'tcx>, } } +impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self) + -> TypeTrace<'tcx> + { + TypeTrace { + cause: cause.clone(), + values: Consts(ExpectedFound::new(a_is_expected, a, b)) + } + } +} + impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a_is_expected: bool, diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 8225ed70c58..413c1428ff9 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -318,8 +318,9 @@ pub fn instantiate_nll_query_response_and_region_obligations( obligations.extend(ok.into_obligations()); } - (UnpackedKind::Const(..), UnpackedKind::Const(..)) => { - unimplemented!() // FIXME(const_generics) + (UnpackedKind::Const(v1), UnpackedKind::Const(v2)) => { + let ok = self.at(cause, param_env).eq(v1, v2)?; + obligations.extend(ok.into_obligations()); } _ => { @@ -626,8 +627,9 @@ fn unify_canonical_vars( obligations .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); } - (UnpackedKind::Const(..), UnpackedKind::Const(..)) => { - unimplemented!() // FIXME(const_generics) + (UnpackedKind::Const(v1), UnpackedKind::Const(v2)) => { + let ok = self.at(cause, param_env).eq(v1, v2)?; + obligations.extend(ok.into_obligations()); } _ => { bug!("kind mismatch, cannot unify {:?} and {:?}", value1, value2,); diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 95b566d4a1b..4b6e7da3330 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1260,6 +1260,7 @@ fn values_str( match *values { infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found), infer::Regions(ref exp_found) => self.expected_found_str(exp_found), + infer::Consts(ref exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found), infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found), } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 5846e604cfc..b5a9184079a 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -232,6 +232,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub enum ValuePairs<'tcx> { Types(ExpectedFound>), Regions(ExpectedFound>), + Consts(ExpectedFound<&'tcx ty::Const<'tcx>>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), } @@ -1730,6 +1731,7 @@ pub fn span(&self) -> Span { impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> { (ValuePairs::Types)(a), (ValuePairs::Regions)(a), + (ValuePairs::Consts)(a), (ValuePairs::TraitRefs)(a), (ValuePairs::PolyTraitRefs)(a), } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 084a5429f26..12427daa383 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1462,8 +1462,8 @@ fn parse_merge_functions(slot: &mut Option, v: Option<&str>) -> the same values as the target option of the same name"), allow_features: Option> = (None, parse_opt_comma_list, [TRACKED], "only allow the listed language features to be enabled in code (space separated)"), - emit_directives: bool = (false, parse_bool, [UNTRACKED], - "emit build directives if producing JSON output"), + emit_artifact_notifications: bool = (false, parse_bool, [UNTRACKED], + "emit notifications after each artifact has been output (only in the JSON format)"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index ad8825bc5de..e8c7965ab4f 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -408,9 +408,6 @@ pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { pub fn next_node_id(&self) -> NodeId { self.reserve_node_ids(1) } - pub(crate) fn current_node_id_count(&self) -> usize { - self.next_node_id.get().as_u32() as usize - } pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &self.parse_sess.span_diagnostic } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 007ff32f327..d9ccbba69d5 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1453,7 +1453,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(ty::ParamTy {name, ..}) = ty.sty { + if let ty::Param(ty::ParamTy {name, .. }) = ty.sty { let infcx = self.infcx; self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var( diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index f0c402789c4..d68e2be9ea0 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3424,7 +3424,7 @@ fn confirm_builtin_unsize_candidate( let mut found = false; for ty in field.walk() { if let ty::Param(p) = ty.sty { - ty_params.insert(p.idx as usize); + ty_params.insert(p.index as usize); found = true; } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 90f62a4d132..be29ea5701b 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -204,7 +204,7 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) { }, Component::Param(p) => { - let ty = tcx.mk_ty_param(p.idx, p.name); + let ty = tcx.mk_ty_param(p.index, p.name); Some(ty::Predicate::TypeOutlives( ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) }, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 19440d0bc64..15524ca6e93 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2715,10 +2715,8 @@ pub fn mk_const_infer( } #[inline] - pub fn mk_ty_param(self, - index: u32, - name: InternedString) -> Ty<'tcx> { - self.mk_ty(Param(ParamTy { idx: index, name: name })) + pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> { + self.mk_ty(Param(ParamTy { index, name: name })) } #[inline] diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cb92e4b7470..7b749957c3f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -979,7 +979,7 @@ pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx GenericParamDef { - if let Some(index) = param.idx.checked_sub(self.parent_count as u32) { + if let Some(index) = param.index.checked_sub(self.parent_count as u32) { let param = &self.params[index as usize]; match param.kind { GenericParamDefKind::Type { .. } => param, diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index d7b19070741..20493413274 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -390,7 +390,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } (&ty::Param(ref a_p), &ty::Param(ref b_p)) - if a_p.idx == b_p.idx => + if a_p.index == b_p.index => { Ok(a) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index bab9527dd07..cf04d6eac3a 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -6,7 +6,7 @@ use crate::hir::def::Namespace; use crate::mir::ProjectionKind; use crate::mir::interpret::ConstValue; -use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid}; +use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -240,7 +240,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl fmt::Debug for ty::ParamTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}/#{}", self.name, self.idx) + write!(f, "{}/#{}", self.name, self.index) } } @@ -1352,8 +1352,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc), - // FIXME(const_generics): implement TypeFoldable for InferConst - ConstValue::Infer(ic) => ConstValue::Infer(ic), + ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)), ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)), ConstValue::Placeholder(p) => ConstValue::Placeholder(p), ConstValue::Scalar(a) => ConstValue::Scalar(a), @@ -1366,8 +1365,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { ConstValue::ByRef(..) => false, - // FIXME(const_generics): implement TypeFoldable for InferConst - ConstValue::Infer(_) => false, + ConstValue::Infer(ic) => ic.visit_with(visitor), ConstValue::Param(p) => p.visit_with(visitor), ConstValue::Placeholder(_) => false, ConstValue::Scalar(_) => false, @@ -1376,3 +1374,13 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } } + +impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _visitor: &mut V) -> bool { + false + } +} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cca40c379fc..760f3d60d05 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1111,13 +1111,13 @@ pub fn abi(&self) -> abi::Abi { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ParamTy { - pub idx: u32, + pub index: u32, pub name: InternedString, } impl<'a, 'gcx, 'tcx> ParamTy { pub fn new(index: u32, name: InternedString) -> ParamTy { - ParamTy { idx: index, name: name } + ParamTy { index, name: name } } pub fn for_self() -> ParamTy { @@ -1129,14 +1129,14 @@ pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { } pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { - tcx.mk_ty_param(self.idx, self.name) + tcx.mk_ty_param(self.index, self.name) } pub fn is_self(&self) -> bool { - // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere, + // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere, // but this should only be possible when using `-Z continue-parse-after-error` like // `compile-fail/issue-36638.rs`. - self.name == keywords::SelfUpper.name().as_str() && self.idx == 0 + self.name == keywords::SelfUpper.name().as_str() && self.index == 0 } } @@ -1763,7 +1763,7 @@ pub fn is_bool(&self) -> bool { self.sty == Bool } pub fn is_param(&self, index: u32) -> bool { match self.sty { - ty::Param(ref data) => data.idx == index, + ty::Param(ref data) => data.index == index, _ => false, } } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 8d51fbc174a..72dfe581ba7 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -547,7 +547,7 @@ fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack()); + let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack()); let ty = match opt_ty { Some(UnpackedKind::Type(ty)) => ty, Some(kind) => { @@ -558,7 +558,7 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { when substituting (root type={:?}) substs={:?}", p, source_ty, - p.idx, + p.index, kind, self.root_ty, self.substs, @@ -572,7 +572,7 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { when substituting (root type={:?}) substs={:?}", p, source_ty, - p.idx, + p.index, self.root_ty, self.substs, ); @@ -618,8 +618,7 @@ fn const_for_param( } }; - // FIXME(const_generics): shift const through binders - ct + self.shift_vars_through_binders(ct) } /// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs @@ -664,15 +663,15 @@ fn const_for_param( /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the /// first case we do not increase the De Bruijn index and in the second case we do. The reason /// is that only in the second case have we passed through a fn binder. - fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", - ty, self.binders_passed, ty.has_escaping_bound_vars()); + fn shift_vars_through_binders>(&self, val: T) -> T { + debug!("shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", + val, self.binders_passed, val.has_escaping_bound_vars()); - if self.binders_passed == 0 || !ty.has_escaping_bound_vars() { - return ty; + if self.binders_passed == 0 || !val.has_escaping_bound_vars() { + return val; } - let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed); + let result = ty::fold::shift_vars(self.tcx(), &val, self.binders_passed); debug!("shift_vars: shifted result = {:?}", result); result diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index f25891d77ce..d5a56f6a09e 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -95,6 +95,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, ); } } + if sess.opts.debugging_opts.emit_artifact_notifications { + sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + } } if sess.opts.cg.save_temps { @@ -1017,12 +1020,10 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, } } - // If we're building a dynamic library then some platforms need to make sure - // that all symbols are exported correctly from the dynamic library. - if crate_type != config::CrateType::Executable || - sess.target.target.options.is_like_emscripten { - cmd.export_symbols(tmpdir, crate_type); - } + // If we're building something like a dynamic library then some platforms + // need to make sure that all symbols are exported correctly from the + // dynamic library. + cmd.export_symbols(tmpdir, crate_type); // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index c99fc17dd89..926f4febe7b 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -372,6 +372,11 @@ fn build_dylib(&mut self, out_filename: &Path) { } fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + // Symbol visibility in object files typically takes care of this. + if crate_type == CrateType::Executable { + return; + } + // If we're compiling a dylib, then we let symbol visibility in object // files to take care of whether they're exported or not. // @@ -645,6 +650,11 @@ fn debuginfo(&mut self) { fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + // Symbol visibility takes care of this typically + if crate_type == CrateType::Executable { + return; + } + let path = tmpdir.join("lib.def"); let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 4fdcdafcab8..a339ec30a74 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -543,12 +543,12 @@ fn from_str(s: &str) -> Result { } } -enum NodesMatchingUII<'a, 'hir: 'a> { +enum NodesMatchingUII<'a> { NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'hir>), + NodesMatchingSuffix(Box + 'a>), } -impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> { +impl<'a> Iterator for NodesMatchingUII<'a> { type Item = ast::NodeId; fn next(&mut self) -> Option { @@ -576,10 +576,12 @@ fn reconstructed_input(&self) -> String { fn all_matching_node_ids<'a, 'hir>(&'a self, map: &'a hir_map::Map<'hir>) - -> NodesMatchingUII<'a, 'hir> { + -> NodesMatchingUII<'a> { match *self { ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), - ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts)), + ItemViaPath(ref parts) => { + NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) + } } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index bfc9113c2d4..59cbd65f05c 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -16,6 +16,7 @@ use std::io::prelude::*; use std::io; use std::cmp::{min, Reverse}; +use std::path::Path; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; use termcolor::{WriteColor, Color, Buffer}; @@ -52,9 +53,10 @@ pub trait Emitter { /// Emit a structured diagnostic. fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>); - /// Emit a JSON directive. The default is to do nothing; this should only - /// be emitted with --error-format=json. - fn maybe_emit_json_directive(&mut self, _directive: String) {} + /// Emit a notification that an artifact has been output. + /// This is currently only supported for the JSON format, + /// other formats can, and will, simply ignore it. + fn emit_artifact_notification(&mut self, _path: &Path) {} /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index e173e1060cc..3aa87fad071 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -26,6 +26,7 @@ use std::cell::Cell; use std::{error, fmt}; use std::panic; +use std::path::Path; use termcolor::{ColorSpec, Color}; @@ -294,16 +295,9 @@ fn description(&self) -> &str { pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, DiagnosticId}; pub use diagnostic_builder::DiagnosticBuilder; -/// A handler deals with two kinds of compiler output. -/// - Errors: certain errors (fatal, bug, unimpl) may cause immediate exit, -/// others log errors for later reporting. -/// - Directives: with --error-format=json, the compiler produces directives -/// that indicate when certain actions have completed, which are useful for -/// Cargo. They may change at any time and should not be considered a public -/// API. -/// -/// This crate's name (rustc_errors) doesn't encompass the directives, because -/// directives were added much later. +/// A handler deals with errors and other compiler output. +/// Certain errors (fatal, bug, unimpl) may cause immediate exit, +/// others log errors for later reporting. pub struct Handler { pub flags: HandlerFlags, @@ -775,8 +769,8 @@ fn emit_db(&self, db: &DiagnosticBuilder<'_>) { } } - pub fn maybe_emit_json_directive(&self, directive: String) { - self.emitter.borrow_mut().maybe_emit_json_directive(directive); + pub fn emit_artifact_notification(&self, path: &Path) { + self.emitter.borrow_mut().emit_artifact_notification(path); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8543cca1dd5..54b3e734205 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1048,14 +1048,11 @@ enum MetadataKind { tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)) }); let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir); - match std::fs::rename(&metadata_filename, &out_filename) { - Ok(_) => { - if tcx.sess.opts.debugging_opts.emit_directives { - tcx.sess.parse_sess.span_diagnostic.maybe_emit_json_directive( - format!("metadata file written: {}", out_filename.display())); - } - } - Err(e) => tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)), + if let Err(e) = fs::rename(&metadata_filename, &out_filename) { + tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + } + if tcx.sess.opts.debugging_opts.emit_artifact_notifications { + tcx.sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f70429c22b6..f7a89271ec5 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -46,7 +46,6 @@ use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::expr_to_string; use syntax::visit::FnKind; -use syntax::struct_span_err; use rustc::hir::{self, GenericParamKind, PatKind}; @@ -1438,15 +1437,10 @@ fn check_ident_token(&mut self, UnderMacro(under_macro): UnderMacro, ident: ast::Ident) { - let ident_str = &ident.as_str()[..]; - let cur_edition = cx.sess.edition(); - let is_raw_ident = |ident: ast::Ident| { - cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) - }; - let next_edition = match cur_edition { + let next_edition = match cx.sess.edition() { Edition::Edition2015 => { - match ident_str { - "async" | "try" => Edition::Edition2018, + match &ident.as_str()[..] { + "async" | "await" | "try" => Edition::Edition2018, // rust-lang/rust#56327: Conservatively do not // attempt to report occurrences of `dyn` within @@ -1462,43 +1456,16 @@ fn check_ident_token(&mut self, // an identifier. "dyn" if !under_macro => Edition::Edition2018, - // Only issue warnings for `await` if the `async_await` - // feature isn't being used. Otherwise, users need - // to keep using `await` for the macro exposed by std. - "await" if !cx.sess.features_untracked().async_await => Edition::Edition2018, _ => return, } } // There are no new keywords yet for the 2018 edition and beyond. - // However, `await` is a "false" keyword in the 2018 edition, - // and can only be used if the `async_await` feature is enabled. - // Otherwise, we emit an error. - _ => { - if "await" == ident_str - && !cx.sess.features_untracked().async_await - && !is_raw_ident(ident) - { - let mut err = struct_span_err!( - cx.sess, - ident.span, - E0721, - "`await` is a keyword in the {} edition", cur_edition, - ); - err.span_suggestion( - ident.span, - "you can use a raw identifier to stay compatible", - "r#await".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } - return - }, + _ => return, }; // don't lint `r#foo` - if is_raw_ident(ident) { + if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { return; } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 160d4c30c0b..c47d7d85a37 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -783,7 +783,7 @@ fn inject_sanitizer_runtime(&mut self) { Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, }; - if !supported_targets.contains(&&*self.sess.target.target.llvm_target) { + if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) { self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target", sanitizer, supported_targets.join("` or `") @@ -794,7 +794,7 @@ fn inject_sanitizer_runtime(&mut self) { // firstyear 2017 - during testing I was unable to access an OSX machine // to make this work on different crate types. As a result, today I have // only been able to test and support linux as a target. - if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" { + if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" { if !self.sess.crate_types.borrow().iter().all(|ct| { match *ct { // Link the runtime diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index ed183acc93b..1a7266859ad 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -77,6 +77,7 @@ fn visit_local(&mut self, loc: &'tcx hir::Local) { hir::LocalSource::Normal => "local binding", hir::LocalSource::ForLoopDesugar => "`for` loop binding", hir::LocalSource::AsyncFn => "async fn binding", + hir::LocalSource::AwaitDesugar => "`await` future binding", }); // Check legality of move bindings and `@` patterns. @@ -412,8 +413,9 @@ fn check_arms<'a, 'tcx>( err.emit(); } - // Unreachable patterns in try expressions occur when one of the arms - // are an uninhabited type. Which is OK. + // Unreachable patterns in try and await expressions occur when one of + // the arms are an uninhabited type. Which is OK. + hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {} } } diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index b001a09529e..999e7402afd 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -3,7 +3,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::interpret::ConstValue; use rustc::session::config::OptLevel; -use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst}; +use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts}; use rustc::ty::subst::{SubstsRef, InternalSubsts}; use syntax::ast; use syntax::attr::InlineAttr; @@ -240,11 +240,11 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Pushes the type name of the specified type to the provided string. - // If 'debug' is true, printing normally unprintable types is allowed - // (e.g. ty::GeneratorWitness). This parameter should only be set when - // this method is being used for logging purposes (e.g. with debug! or info!) - // When being used for codegen purposes, 'debug' should be set to 'false' - // in order to catch unexpected types that should never end up in a type name + // If `debug` is true, printing normally unprintable types is allowed + // (e.g. `ty::GeneratorWitness`). This parameter should only be set when + // this method is being used for logging purposes (e.g. with `debug!` or `info!`) + // When being used for codegen purposes, `debug` should be set to `false` + // in order to catch unexpected types that should never end up in a type name. pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) { match t.sty { ty::Bool => output.push_str("bool"), @@ -387,22 +387,34 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) { if debug { output.push_str(&format!("`{:?}`", t)); } else { - bug!("DefPathBasedNames: Trying to create type name for \ - unexpected type: {:?}", t); + bug!( + "DefPathBasedNames: trying to create type name for unexpected type: {:?}", + t, + ); } } } } - // FIXME(const_generics): handle debug printing. + // Pushes the the name of the specified const to the provided string. + // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed, + // as well as the unprintable types of constants (see `push_type_name` for more details). pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) { match c.val { - ConstValue::Infer(..) | ConstValue::Placeholder(_) => output.push_str("_"), - ConstValue::Param(ParamConst { name, .. }) => { - write!(output, "{}", name).unwrap(); + ConstValue::Scalar(..) | ConstValue::Slice(..) | ConstValue::ByRef(..) => { + // FIXME(const_generics): we could probably do a better job here. + write!(output, "{:?}", c).unwrap() + } + _ => { + if debug { + write!(output, "{:?}", c).unwrap() + } else { + bug!( + "DefPathBasedNames: trying to create const name for unexpected const: {:?}", + c, + ); + } } - ConstValue::Unevaluated(..) => output.push_str("_: _"), - _ => write!(output, "{:?}", c).unwrap(), } output.push_str(": "); self.push_type_name(c.ty, output, debug); diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index c21f7f38ca5..9dd343b6c8d 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -14,13 +14,7 @@ pub fn opts() -> TargetOptions { // // Here we detect what version is being requested, defaulting to 10.7. ELF // TLS is flagged as enabled if it looks to be supported. - let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); - let version = deployment_target.as_ref().and_then(|s| { - let mut i = s.splitn(2, '.'); - i.next().and_then(|a| i.next().map(|b| (a, b))) - }).and_then(|(a, b)| { - a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() - }).unwrap_or((10, 7)); + let version = macos_deployment_target().unwrap_or((10, 7)); TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections @@ -40,3 +34,27 @@ pub fn opts() -> TargetOptions { .. Default::default() } } + +fn macos_deployment_target() -> Option<(u32, u32)> { + let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); + let version = deployment_target.as_ref().and_then(|s| { + let mut i = s.splitn(2, '.'); + i.next().and_then(|a| i.next().map(|b| (a, b))) + }).and_then(|(a, b)| { + a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() + }); + + version +} + +pub fn macos_llvm_target(arch: &str) -> String { + let version = macos_deployment_target(); + let llvm_target = match version { + Some((major, minor)) => { + format!("{}-apple-macosx{}.{}.0", arch, major, minor) + }, + None => format!("{}-apple-darwin", arch) + }; + + llvm_target +} diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index 58c59cc8728..7d804ea53fb 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -8,8 +8,14 @@ pub fn target() -> TargetResult { base.stack_probes = true; base.eliminate_frame_pointer = false; + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + let arch = "i686"; + let llvm_target = super::apple_base::macos_llvm_target(&arch); + Ok(Target { - llvm_target: "i686-apple-darwin".to_string(), + llvm_target: llvm_target, target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index c54181741b3..182103440f0 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -8,13 +8,19 @@ pub fn target() -> TargetResult { base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); base.stack_probes = true; + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + let arch = "x86_64"; + let llvm_target = super::apple_base::macos_llvm_target(&arch); + Ok(Target { - llvm_target: "x86_64-apple-darwin".to_string(), + llvm_target: llvm_target, target_endian: "little".to_string(), target_pointer_width: "64".to_string(), target_c_int_width: "32".to_string(), data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(), - arch: "x86_64".to_string(), + arch: arch.to_string(), target_os: "macos".to_string(), target_env: String::new(), target_vendor: "apple".to_string(), diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 838874cc2bf..3fa192f16f3 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -246,7 +246,7 @@ fn deduce_expectations_from_obligations( } /// Given a projection like "::Result == Y", we can deduce - /// everything we need to know about a closure. + /// everything we need to know about a closure or generator. /// /// The `cause_span` should be the span that caused us to /// have this expected signature, or `None` if we can't readily @@ -262,37 +262,50 @@ fn deduce_sig_from_projection( let trait_ref = projection.to_poly_trait_ref(tcx); - if tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_none() { + let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); + let gen_trait = tcx.lang_items().gen_trait().unwrap(); + let is_gen = gen_trait == trait_ref.def_id(); + if !is_fn && !is_gen { + debug!("deduce_sig_from_projection: not fn or generator"); return None; } - let arg_param_ty = trait_ref.skip_binder().substs.type_at(1); - let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); - debug!( - "deduce_sig_from_projection: arg_param_ty {:?}", - arg_param_ty - ); + if is_gen { + // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return` + // associated item and not yield. + let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id; + if return_assoc_item != projection.projection_def_id() { + debug!("deduce_sig_from_projection: not return assoc item of generator"); + return None; + } + } + + let input_tys = if is_fn { + let arg_param_ty = trait_ref.skip_binder().substs.type_at(1); + let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); + debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); - let input_tys = match arg_param_ty.sty { - ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()), - _ => return None, + match arg_param_ty.sty { + ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::>(), + _ => return None, + } + } else { + // Generators cannot have explicit arguments. + vec![] }; let ret_param_ty = projection.skip_binder().ty; let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty); - debug!( - "deduce_sig_from_projection: ret_param_ty {:?}", - ret_param_ty - ); + debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty); let sig = self.tcx.mk_fn_sig( - input_tys, - ret_param_ty, + input_tys.iter(), + &ret_param_ty, false, hir::Unsafety::Normal, Abi::Rust, ); - debug!("deduce_sig_from_projection: sig {:?}", sig); + debug!("deduce_sig_from_projection: sig={:?}", sig); Some(ExpectedSig { cause_span, sig }) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 314f7e97cd2..251400e65f3 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -757,8 +757,7 @@ fn assemble_inherent_candidates_from_object(&mut self, }); } - fn assemble_inherent_candidates_from_param(&mut self, - param_ty: ty::ParamTy) { + fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { // FIXME -- Do we want to commit to this behavior for param bounds? let bounds = self.param_env diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e404a8e6972..64c8ff8ff86 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5785,8 +5785,6 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty ); - // FIXME(const_generics): we probably want to check the bounds for const parameters too. - if own_counts.types == 0 { return; } @@ -5795,9 +5793,9 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut types_used = vec![false; own_counts.types]; for leaf_ty in ty.walk() { - if let ty::Param(ty::ParamTy { idx, .. }) = leaf_ty.sty { - debug!("Found use of ty param num {}", idx); - types_used[idx as usize - own_counts.lifetimes] = true; + if let ty::Param(ty::ParamTy { index, .. }) = leaf_ty.sty { + debug!("Found use of ty param num {}", index); + types_used[index as usize - own_counts.lifetimes] = true; } else if let ty::Error = leaf_ty.sty { // If there is already another error, do not emit // an error for not using a type Parameter. diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1420c66c73e..fd7d6fe694c 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -494,7 +494,7 @@ struct CountParams { params: FxHashSet } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { if let ty::Param(param) = t.sty { - self.params.insert(param.idx); + self.params.insert(param.index); } t.super_visit_with(self) } diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index 18bf66ceb35..49910e39fed 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -8,7 +8,7 @@ pub struct Parameter(pub u32); impl From for Parameter { - fn from(param: ty::ParamTy) -> Self { Parameter(param.idx) } + fn from(param: ty::ParamTy) -> Self { Parameter(param.index) } } impl From for Parameter { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 5079a3bb55f..4f82978f01a 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -324,7 +324,7 @@ fn add_constraints_from_ty(&mut self, } ty::Param(ref data) => { - self.add_constraint(current, data.idx, variance); + self.add_constraint(current, data.index, variance); } ty::FnPtr(sig) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de74a6a5400..3a260db8065 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1706,9 +1706,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics { } Some(param.clean(cx)) } - ty::GenericParamDefKind::Const { .. } => { - unimplemented!() // FIXME(const_generics) - } + ty::GenericParamDefKind::Const { .. } => None, }).collect::>(); let mut where_predicates = preds.predicates.iter() diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4204d20498d..880b8243355 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1052,6 +1052,10 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { height: 45px; } + .rustdoc.source > .sidebar > .sidebar-menu { + display: none; + } + .sidebar-elems { position: fixed; z-index: 1; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 8ef8c2b4c0a..36a1628014d 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -764,12 +764,18 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -impl Encodable for path::PathBuf { +impl Encodable for path::Path { fn encode(&self, e: &mut S) -> Result<(), S::Error> { self.to_str().unwrap().encode(e) } } +impl Encodable for path::PathBuf { + fn encode(&self, e: &mut S) -> Result<(), S::Error> { + path::Path::encode(self, e) + } +} + impl Decodable for path::PathBuf { fn decode(d: &mut D) -> Result { let bytes: String = Decodable::decode(d)?; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index ac1aff845d8..ad5d62f667a 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.9" } +compiler_builtins = { version = "0.1.12" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 33b8c76bb53..af2302d24f5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1065,6 +1065,7 @@ pub fn precedence(&self) -> ExprPrecedence { ExprKind::Block(..) => ExprPrecedence::Block, ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, ExprKind::Async(..) => ExprPrecedence::Async, + ExprKind::Await(..) => ExprPrecedence::Await, ExprKind::Assign(..) => ExprPrecedence::Assign, ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, ExprKind::Field(..) => ExprPrecedence::Field, @@ -1186,6 +1187,9 @@ pub enum ExprKind { /// created during lowering cannot be made the parent of any other /// preexisting defs. Async(CaptureBy, NodeId, P), + /// An await expression (`my_future.await`). + Await(AwaitOrigin, P), + /// A try block (`try { ... }`). TryBlock(P), @@ -1287,6 +1291,15 @@ pub enum Movability { Movable, } +/// Whether an `await` comes from `await!` or `.await` syntax. +/// FIXME: this should be removed when support for legacy `await!` is removed. +/// https://github.com/rust-lang/rust/issues/60610 +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +pub enum AwaitOrigin { + FieldLike, + MacroLike, +} + pub type Mac = Spanned; /// Represents a macro invocation. The `Path` indicates which macro diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2a1f3c48014..c3bad3aba18 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -108,8 +108,8 @@ pub fn walk_feature_fields(&self, mut f: F) // was set. This is most important for knowing when a particular feature became // stable (active). // -// Note that the features should be grouped into internal/user-facing -// and then sorted by version inside those groups. This is inforced with tidy. +// Note that the features are grouped into internal/user-facing and then +// sorted by version inside those groups. This is inforced with tidy. // // N.B., `tools/tidy/src/features.rs` parses this information directly out of the // source, so take care when modifying it. @@ -119,7 +119,7 @@ pub fn walk_feature_fields(&self, mut f: F) // feature-group-start: internal feature gates // ------------------------------------------------------------------------- - // no tracking issue START + // no-tracking-issue-start // Allows using the `rust-intrinsic`'s "ABI". (active, intrinsics, "1.0.0", None, None), @@ -152,7 +152,7 @@ pub fn walk_feature_fields(&self, mut f: F) // lets a function to be `const` when opted into with `#![feature(foo)]`. (active, rustc_const_unstable, "1.0.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Allows using `#[link_name="llvm.*"]`. (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), @@ -187,20 +187,17 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows using `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), - // no tracking issue START + // no-tracking-issue-start // Allows using `#[prelude_import]` on glob `use` items. (active, prelude_import, "1.2.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (active, dropck_parametricity, "1.3.0", Some(28498), None), - // FIXME(Centril): Investigate whether this gate actually has any effect. - (active, needs_allocator, "1.4.0", Some(27389), None), - - // no tracking issue START + // no-tracking-issue-start // Allows using `#[omit_gdb_pretty_printer_section]`. (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), @@ -208,7 +205,7 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows using the `vectorcall` ABI. (active, abi_vectorcall, "1.7.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Allows using `#[structural_match]` which indicates that a type is structurally matchable. (active, structural_match, "1.8.0", Some(31434), None), @@ -222,7 +219,7 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. (active, needs_panic_runtime, "1.10.0", Some(32837), None), - // no tracking issue START + // no-tracking-issue-start // Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), @@ -245,7 +242,7 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows using the `format_args_nl` macro. (active, format_args_nl, "1.29.0", None, None), - // no tracking issue END + // no-tracking-issue-end // Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), @@ -485,6 +482,10 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows async and await syntax. (active, async_await, "1.28.0", Some(50547), None), + // Allows await! macro-like syntax. + // This will likely be removed prior to stabilization of async/await. + (active, await_macro, "1.28.0", Some(50547), None), + // Allows reinterpretation of the bits of a value of one type as another type during const eval. (active, const_transmute, "1.29.0", Some(53605), None), @@ -567,6 +568,10 @@ pub fn walk_feature_fields(&self, mut f: F) ]; declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: removed features + // ------------------------------------------------------------------------- + (removed, import_shadowing, "1.0.0", None, None, None), (removed, managed_boxes, "1.0.0", None, None, None), // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 @@ -581,7 +586,6 @@ pub fn walk_feature_fields(&self, mut f: F) (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), // Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None, None), - (removed, pushpop_unsafe, "1.2.0", None, None, None), (removed, allocator, "1.0.0", None, None, None), (removed, simd, "1.0.0", Some(27731), None, Some("removed in favor of `#[repr(simd)]`")), @@ -589,6 +593,9 @@ pub fn walk_feature_fields(&self, mut f: F) Some("merged into `#![feature(slice_patterns)]`")), (removed, macro_reexport, "1.0.0", Some(29638), None, Some("subsumed by `pub use`")), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, needs_allocator, "1.4.0", Some(27389), None, + Some("subsumed by `#![feature(allocator_internals)]`")), (removed, proc_macro_mod, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, @@ -600,12 +607,16 @@ pub fn walk_feature_fields(&self, mut f: F) (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.0.0", Some(29644), None, + (removed, custom_derive, "1.32.0", Some(29644), None, Some("subsumed by `#[proc_macro_derive]`")), // Paths of the form: `extern::foo::bar` (removed, extern_in_paths, "1.33.0", Some(55600), None, Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.0.0", Some(29601), None, None), + (removed, quote, "1.33.0", Some(29601), None, None), + + // ------------------------------------------------------------------------- + // feature-group-end: removed features + // ------------------------------------------------------------------------- ); declare_features! ( @@ -613,6 +624,10 @@ pub fn walk_feature_fields(&self, mut f: F) ); declare_features! ( + // ------------------------------------------------------------------------- + // feature-group-start: for testing purposes + // ------------------------------------------------------------------------- + // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. (accepted, issue_5723_bootstrap, "1.0.0", None, None), @@ -620,6 +635,14 @@ pub fn walk_feature_fields(&self, mut f: F) // they don't actually mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), + // ------------------------------------------------------------------------- + // feature-group-end: for testing purposes + // ------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- + // feature-group-start: accepted features + // ------------------------------------------------------------------------- + // Allows using associated `type`s in `trait`s. (accepted, associated_types, "1.0.0", None, None), // Allows using assigning a default type to type parameters in algebraic data type definitions. @@ -809,6 +832,10 @@ pub fn walk_feature_fields(&self, mut f: F) (accepted, extern_crate_self, "1.34.0", Some(56409), None), // Allows arbitrary delimited token streams in non-macro attributes. (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), + + // ------------------------------------------------------------------------- + // feature-group-end: accepted features + // ------------------------------------------------------------------------- ); // If you change this, please modify `src/doc/unstable-book` as well. You must @@ -2104,6 +2131,20 @@ fn visit_expr(&mut self, e: &'a ast::Expr) { ast::ExprKind::Async(..) => { gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); } + ast::ExprKind::Await(origin, _) => { + match origin { + ast::AwaitOrigin::FieldLike => + gate_feature_post!(&self, async_await, e.span, "async/await is unstable"), + ast::AwaitOrigin::MacroLike => + gate_feature_post!( + &self, + await_macro, + e.span, + "`await!()` macro syntax is unstable, and will soon be removed \ + in favor of `.await` syntax." + ), + } + } _ => {} } visit::walk_expr(self, e); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 65f8d0e77d7..2dd2ecb7493 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -19,6 +19,7 @@ use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan}; use rustc_data_structures::sync::{self, Lrc}; use std::io::{self, Write}; +use std::path::Path; use std::vec; use std::sync::{Arc, Mutex}; @@ -91,15 +92,15 @@ fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { } } - fn maybe_emit_json_directive(&mut self, directive: String) { - let data = Directive { directive }; + fn emit_artifact_notification(&mut self, path: &Path) { + let data = ArtifactNotification { artifact: path }; let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { writeln!(&mut self.dst, "{}", as_json(&data)) }; if let Err(e) = result { - panic!("failed to print message: {:?}", e); + panic!("failed to print notification: {:?}", e); } } } @@ -181,9 +182,9 @@ struct DiagnosticCode { } #[derive(RustcEncodable)] -struct Directive { - /// The directive itself. - directive: String, +struct ArtifactNotification<'a> { + /// The path of the artifact. + artifact: &'a Path, } impl Diagnostic { diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 2e09235ca77..6eb8b1b5004 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1185,6 +1185,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, vis.visit_id(node_id); vis.visit_block(body); } + ExprKind::Await(_origin, expr) => vis.visit_expr(expr), ExprKind::Assign(el, er) => { vis.visit_expr(el); vis.visit_expr(er); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab335..f3eac71ee77 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1576,7 +1576,7 @@ fn parse_trait_item_(&mut self, let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { + let mut decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a // definition... @@ -1585,7 +1585,7 @@ fn parse_trait_item_(&mut self, p.parse_arg_general(p.span.rust_2018(), true, false) })?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &d); + self.construct_async_arguments(&mut asyncness, &mut decl); let sig = ast::MethodSig { header: FnHeader { @@ -1594,7 +1594,7 @@ fn parse_trait_item_(&mut self, abi, asyncness, }, - decl: d, + decl, }; let body = match self.token { @@ -2319,7 +2319,8 @@ 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 { - token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true, + token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) + | token::LArrow => true, _ => false, }; let check_args_start = |this: &mut Self| { @@ -2751,6 +2752,14 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { db.span_label(self.span, "expected expression"); db.note("variable declaration using `let` is a statement"); return Err(db); + } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + // FIXME: remove this branch when `await!` is no longer supported + // https://github.com/rust-lang/rust/issues/60610 + self.expect(&token::Not)?; + self.expect(&token::OpenDelim(token::Paren))?; + let expr = self.parse_expr()?; + self.expect(&token::CloseDelim(token::Paren))?; + ex = ExprKind::Await(ast::AwaitOrigin::MacroLike, expr); } else if self.token.is_path_start() { let path = self.parse_path(PathStyle::Expr)?; @@ -3014,6 +3023,15 @@ fn parse_dot_or_call_expr_with(&mut self, // Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { + if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + let span = lo.to(self.prev_span); + let await_expr = self.mk_expr( + span, + ExprKind::Await(ast::AwaitOrigin::FieldLike, self_arg), + ThinVec::new(), + ); + return Ok(await_expr); + } let segment = self.parse_path_segment(PathStyle::Expr)?; self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); @@ -6045,10 +6063,6 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec, Vec PResult<'a, (Vec, Vec PResult<'a, ItemInfo> { let (ident, mut generics) = self.parse_fn_header()?; let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe; - let decl = self.parse_fn_decl(allow_c_variadic)?; + let mut decl = self.parse_fn_decl(allow_c_variadic)?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - self.construct_async_arguments(&mut asyncness, &decl); + self.construct_async_arguments(&mut asyncness, &mut decl); let header = FnHeader { unsafety, asyncness, constness, abi }; Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) } @@ -6666,9 +6678,9 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool) let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; + let mut decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &decl); + self.construct_async_arguments(&mut asyncness, &mut decl); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let header = ast::FnHeader { abi, unsafety, constness, asyncness }; @@ -8714,9 +8726,9 @@ fn eat_bad_pub(&mut self) { /// /// The arguments of the function are replaced in HIR lowering with the arguments created by /// this function and the statements created here are inserted at the top of the closure body. - fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &FnDecl) { + fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &mut FnDecl) { if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { - for (index, input) in decl.inputs.iter().enumerate() { + for (index, input) in decl.inputs.iter_mut().enumerate() { let id = ast::DUMMY_NODE_ID; let span = input.pat.span; @@ -8728,8 +8740,10 @@ fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: // `let = __argN;` statement, instead just adding a `let = ;` // statement. let (binding_mode, ident, is_simple_pattern) = match input.pat.node { - PatKind::Ident(binding_mode, ident, _) => (binding_mode, ident, true), - _ => (BindingMode::ByValue(Mutability::Immutable), ident, false), + PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { + (binding_mode, ident, true) + } + _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), }; // Construct an argument representing `__argN: ` to replace the argument of the @@ -8796,6 +8810,15 @@ fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: }) }; + // Remove mutability from arguments. If this is not a simple pattern, + // those arguments are replaced by `__argN`, so there is no need to do this. + if let PatKind::Ident(BindingMode::ByValue(mutability @ Mutability::Mutable), ..) = + &mut input.pat.node + { + assert!(is_simple_pattern); + *mutability = Mutability::Immutable; + } + let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2fa4f5263fb..fd7a39c576d 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -99,6 +99,11 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool { ident_token.is_path_segment_keyword() || [ keywords::Async.name(), + + // FIXME: remove when `await!(..)` syntax is removed + // https://github.com/rust-lang/rust/issues/60610 + keywords::Await.name(), + keywords::Do.name(), keywords::Box.name(), keywords::Break.name(), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6c0fdfaa776..682621d40ab 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2250,6 +2250,18 @@ fn print_expr_outer_attr_style(&mut self, self.ibox(0)?; self.print_block_with_attrs(blk, attrs)?; } + ast::ExprKind::Await(origin, ref expr) => { + match origin { + ast::AwaitOrigin::MacroLike => { + self.s.word("await!")?; + self.print_expr_maybe_paren(expr, parser::PREC_FORCE_PAREN)?; + } + ast::AwaitOrigin::FieldLike => { + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?; + self.s.word(".await")?; + } + } + } ast::ExprKind::Assign(ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1)?; diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 5f15ede7b0b..80dabffaba9 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -267,6 +267,7 @@ pub enum ExprPrecedence { TryBlock, Struct, Async, + Await, Err, } @@ -301,6 +302,7 @@ pub fn order(self) -> i8 { ExprPrecedence::Unary => PREC_PREFIX, // Unary, postfix + ExprPrecedence::Await | ExprPrecedence::Call | ExprPrecedence::MethodCall | ExprPrecedence::Field | @@ -346,6 +348,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { // X { y: 1 } + X { y: 2 } contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) } + ast::ExprKind::Await(_, ref x) | ast::ExprKind::Unary(_, ref x) | ast::ExprKind::Cast(ref x, _) | ast::ExprKind::Type(ref x, _) | diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index fc99d10b0b6..0503e5644db 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -768,6 +768,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Async(_, _, ref body) => { visitor.visit_block(body); } + ExprKind::Await(_, ref expr) => visitor.visit_expr(expr), ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { visitor.visit_expr(left_hand_expression); visitor.visit_expr(right_hand_expression); diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index c806020039d..a901afdff43 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -598,6 +598,7 @@ pub enum CompilerDesugaringKind { /// `impl Trait` with `Foo`. ExistentialReturnType, Async, + Await, ForLoop, } @@ -605,6 +606,7 @@ impl CompilerDesugaringKind { pub fn name(self) -> Symbol { Symbol::intern(match self { CompilerDesugaringKind::Async => "async", + CompilerDesugaringKind::Await => "await", CompilerDesugaringKind::QuestionMark => "?", CompilerDesugaringKind::TryBlock => "try block", CompilerDesugaringKind::ExistentialReturnType => "existential type", diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index cdbfabae7ce..20759217b54 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -84,6 +84,7 @@ // Edition-specific keywords that are used in unstable Rust or reserved for future use. Async: "async", // >= 2018 Edition only + Await: "await", // >= 2018 Edition only Try: "try", // >= 2018 Edition only // Special lifetime names diff --git a/src/test/codegen/i686-macosx-deployment-target.rs b/src/test/codegen/i686-macosx-deployment-target.rs new file mode 100644 index 00000000000..dad376d6677 --- /dev/null +++ b/src/test/codegen/i686-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set. +// See issue #60235. + +// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib +// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "i686-apple-macosx10.9.0" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/test/codegen/i686-no-macosx-deployment-target.rs b/src/test/codegen/i686-no-macosx-deployment-target.rs new file mode 100644 index 00000000000..eb826590523 --- /dev/null +++ b/src/test/codegen/i686-no-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we leave the target alone MACOSX_DEPLOYMENT_TARGET is unset. +// See issue #60235. + +// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib +// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "i686-apple-darwin" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/test/codegen/x86_64-macosx-deployment-target.rs b/src/test/codegen/x86_64-macosx-deployment-target.rs new file mode 100644 index 00000000000..8e291b7b298 --- /dev/null +++ b/src/test/codegen/x86_64-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set. +// See issue #60235. + +// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib +// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "x86_64-apple-macosx10.9.0" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/test/codegen/x86_64-no-macosx-deployment-target.rs b/src/test/codegen/x86_64-no-macosx-deployment-target.rs new file mode 100644 index 00000000000..58a11d1095b --- /dev/null +++ b/src/test/codegen/x86_64-no-macosx-deployment-target.rs @@ -0,0 +1,26 @@ +// +// Checks that we leave the target alone when MACOSX_DEPLOYMENT_TARGET is unset. +// See issue #60235. + +// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib +// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: target triple = "x86_64-apple-darwin" +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +} diff --git a/src/test/run-make/wasm-export-all-symbols/Makefile b/src/test/run-make/wasm-export-all-symbols/Makefile index 039481215f0..15403d8d410 100644 --- a/src/test/run-make/wasm-export-all-symbols/Makefile +++ b/src/test/run-make/wasm-export-all-symbols/Makefile @@ -6,8 +6,14 @@ all: $(RUSTC) bar.rs --target wasm32-unknown-unknown $(RUSTC) foo.rs --target wasm32-unknown-unknown $(NODE) verify.js $(TMPDIR)/foo.wasm + $(RUSTC) main.rs --target wasm32-unknown-unknown + $(NODE) verify.js $(TMPDIR)/main.wasm $(RUSTC) bar.rs --target wasm32-unknown-unknown -O $(RUSTC) foo.rs --target wasm32-unknown-unknown -O $(NODE) verify.js $(TMPDIR)/foo.wasm + $(RUSTC) main.rs --target wasm32-unknown-unknown -O + $(NODE) verify.js $(TMPDIR)/main.wasm $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto $(NODE) verify.js $(TMPDIR)/foo.wasm + $(RUSTC) main.rs --target wasm32-unknown-unknown -C lto + $(NODE) verify.js $(TMPDIR)/main.wasm diff --git a/src/test/run-make/wasm-export-all-symbols/main.rs b/src/test/run-make/wasm-export-all-symbols/main.rs new file mode 100644 index 00000000000..0edda7d7b88 --- /dev/null +++ b/src/test/run-make/wasm-export-all-symbols/main.rs @@ -0,0 +1,3 @@ +extern crate bar; + +fn main() {} diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js index 0f56fa45c22..7b6fc7a4568 100644 --- a/src/test/run-make/wasm-export-all-symbols/verify.js +++ b/src/test/run-make/wasm-export-all-symbols/verify.js @@ -16,7 +16,13 @@ for (const entry of list) { nexports += 1; } -if (nexports != 1) - throw new Error("should only have one function export"); if (my_exports.foo === undefined) throw new Error("`foo` wasn't defined"); + +if (my_exports.main === undefined) { + if (nexports != 1) + throw new Error("should only have one function export"); +} else { + if (nexports != 2) + throw new Error("should only have two function exports"); +} diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index e1b4328debd..49fd8b8b1ce 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -1,7 +1,7 @@ // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await, await_macro)] +#![feature(async_await)] extern crate arc_wake; @@ -46,14 +46,14 @@ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { fn async_block(x: u8) -> impl Future { async move { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } } fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { async move { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } } @@ -61,43 +61,43 @@ fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future impl Future { async move { let future = async { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x }; - await!(future) + future.await } } fn async_closure(x: u8) -> impl Future { (async move |x: u8| -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x })(x) } async fn async_fn(x: u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } async fn generic_async_fn(x: T) -> T { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } async fn async_fn_with_borrow(x: &u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { async move { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } } @@ -110,18 +110,18 @@ async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 { */ async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; *x } fn async_fn_with_internal_borrow(y: u8) -> impl Future { async move { - await!(async_fn_with_borrow_named_lifetime(&y)) + async_fn_with_borrow_named_lifetime(&y).await } } unsafe async fn unsafe_async_fn(x: u8) -> u8 { - await!(wake_and_yield_once()); + wake_and_yield_once().await; x } @@ -134,7 +134,7 @@ fn foo() {} impl Foo { async fn async_method(x: u8) -> u8 { unsafe { - await!(unsafe_async_fn(x)) + unsafe_async_fn(x).await } } } @@ -165,7 +165,7 @@ macro_rules! test_with_borrow { ($($fn_name:expr,)*) => { $( test_future_yields_once_then_returns(|x| { async move { - await!($fn_name(&x)) + $fn_name(&x).await } }); )* } @@ -181,7 +181,7 @@ macro_rules! test_with_borrow { Foo::async_method, |x| { async move { - unsafe { await!(unsafe_async_fn(x)) } + unsafe { unsafe_async_fn(x).await } } }, } @@ -192,7 +192,7 @@ macro_rules! test_with_borrow { async_fn_with_impl_future_named_lifetime, |x| { async move { - await!(async_fn_multiple_args_named_lifetime(x, x)) + async_fn_multiple_args_named_lifetime(x, x).await } }, } diff --git a/src/test/run-pass/await-macro.rs b/src/test/run-pass/await-macro.rs new file mode 100644 index 00000000000..e1b4328debd --- /dev/null +++ b/src/test/run-pass/await-macro.rs @@ -0,0 +1,199 @@ +// edition:2018 +// aux-build:arc_wake.rs + +#![feature(async_await, await_macro)] + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool); + +fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } + +impl Future for WakeOnceThenComplete { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.0 { + Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn async_block(x: u8) -> impl Future { + async move { + await!(wake_and_yield_once()); + x + } +} + +fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { + async move { + await!(wake_and_yield_once()); + *x + } +} + +fn async_nonmove_block(x: u8) -> impl Future { + async move { + let future = async { + await!(wake_and_yield_once()); + x + }; + await!(future) + } +} + +fn async_closure(x: u8) -> impl Future { + (async move |x: u8| -> u8 { + await!(wake_and_yield_once()); + x + })(x) +} + +async fn async_fn(x: u8) -> u8 { + await!(wake_and_yield_once()); + x +} + +async fn generic_async_fn(x: T) -> T { + await!(wake_and_yield_once()); + x +} + +async fn async_fn_with_borrow(x: &u8) -> u8 { + await!(wake_and_yield_once()); + *x +} + +async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 { + await!(wake_and_yield_once()); + *x +} + +fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { + async move { + await!(wake_and_yield_once()); + *x + } +} + +/* FIXME(cramertj) support when `existential type T<'a, 'b>:;` works +async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 { + await!(wake_and_yield_once()); + *x +} +*/ + +async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 { + await!(wake_and_yield_once()); + *x +} + +fn async_fn_with_internal_borrow(y: u8) -> impl Future { + async move { + await!(async_fn_with_borrow_named_lifetime(&y)) + } +} + +unsafe async fn unsafe_async_fn(x: u8) -> u8 { + await!(wake_and_yield_once()); + x +} + +struct Foo; + +trait Bar { + fn foo() {} +} + +impl Foo { + async fn async_method(x: u8) -> u8 { + unsafe { + await!(unsafe_async_fn(x)) + } + } +} + +fn test_future_yields_once_then_returns(f: F) +where + F: FnOnce(u8) -> Fut, + Fut: Future, +{ + let mut fut = Box::pin(f(9)); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx)); + assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx)); +} + +fn main() { + macro_rules! test { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns($fn_name); + )* } + } + + macro_rules! test_with_borrow { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns(|x| { + async move { + await!($fn_name(&x)) + } + }); + )* } + } + + test! { + async_block, + async_nonmove_block, + async_closure, + async_fn, + generic_async_fn, + async_fn_with_internal_borrow, + Foo::async_method, + |x| { + async move { + unsafe { await!(unsafe_async_fn(x)) } + } + }, + } + test_with_borrow! { + async_block_with_borrow_named_lifetime, + async_fn_with_borrow, + async_fn_with_borrow_named_lifetime, + async_fn_with_impl_future_named_lifetime, + |x| { + async move { + await!(async_fn_multiple_args_named_lifetime(x, x)) + } + }, + } +} diff --git a/src/test/run-pass/generator/issue-59972.rs b/src/test/run-pass/generator/issue-59972.rs new file mode 100644 index 00000000000..995da4fb3ff --- /dev/null +++ b/src/test/run-pass/generator/issue-59972.rs @@ -0,0 +1,23 @@ +// compile-flags: --edition=2018 + +#![feature(async_await, await_macro)] + +pub enum Uninhabited { } + +fn uninhabited_async() -> Uninhabited { + unreachable!() +} + +async fn noop() { } + +#[allow(unused)] +async fn contains_never() { + let error = uninhabited_async(); + await!(noop()); + let error2 = error; +} + +#[allow(unused_must_use)] +fn main() { + contains_never(); +} diff --git a/src/test/run-pass/issue-55809.rs b/src/test/run-pass/issue-55809.rs index 12be6582a21..b7e60b773b4 100644 --- a/src/test/run-pass/issue-55809.rs +++ b/src/test/run-pass/issue-55809.rs @@ -1,7 +1,7 @@ // edition:2018 // run-pass -#![feature(async_await, await_macro)] +#![feature(async_await)] trait Foo { } @@ -14,15 +14,15 @@ async fn foo_async(_v: T) -> u8 where T: Foo { } async fn bad(v: T) -> u8 where T: Foo { - await!(foo_async(v)) + foo_async(v).await } async fn async_main() { let mut v = (); - let _ = await!(bad(&mut v)); - let _ = await!(foo_async(&mut v)); - let _ = await!(bad(v)); + let _ = bad(&mut v).await; + let _ = foo_async(&mut v).await; + let _ = bad(v).await; } fn main() { diff --git a/src/test/ui/async-await/argument-patterns.rs b/src/test/ui/async-await/argument-patterns.rs new file mode 100644 index 00000000000..3750c2bcb70 --- /dev/null +++ b/src/test/ui/async-await/argument-patterns.rs @@ -0,0 +1,30 @@ +// edition:2018 +// run-pass + +#![allow(unused_variables)] +#![deny(unused_mut)] +#![feature(async_await)] + +type A = Vec; + +async fn a(n: u32, mut vec: A) { + vec.push(n); +} + +async fn b(n: u32, ref mut vec: A) { + vec.push(n); +} + +async fn c(ref vec: A) { + vec.contains(&0); +} + +async fn d((a, mut b): (A, A)) { + b.push(1); +} + +async fn f((ref mut a, ref b): (A, A)) {} + +async fn g(((ref a, ref mut b), (ref mut c, ref d)): ((A, A), (A, A))) {} + +fn main() {} diff --git a/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs b/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs new file mode 100644 index 00000000000..c2b59eecb99 --- /dev/null +++ b/src/test/ui/async-await/drop-order-for-async-fn-parameters-by-ref-binding.rs @@ -0,0 +1,271 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +#![allow(unused_variables)] +#![feature(async_await, await_macro)] + +// Test that the drop order for parameters in a fn and async fn matches up. Also test that +// parameters (used or unused) are not dropped until the async fn completes execution. +// See also #54716. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::marker::PhantomData; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check that unused bindings are dropped after the function is polled. +async fn foo_async(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foo_sync(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns are dropped after the function is polled. +async fn bar_async(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn bar_sync(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns within more complex patterns are dropped after the function +/// is polled. +async fn baz_async((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn baz_sync((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore and unused bindings within and outwith more complex patterns are dropped +/// after the function is polled. +async fn foobar_async(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foobar_sync(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +struct Foo; + +impl Foo { + /// Check that unused bindings are dropped after the method is polled. + async fn foo_async(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method is polled. + async fn bar_async(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// is polled. + async fn baz_async((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method is polled. + async fn foobar_async( + ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync( + ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +struct Bar<'a>(PhantomData<&'a ()>); + +impl<'a> Bar<'a> { + /// Check that unused bindings are dropped after the method with self is polled. + async fn foo_async(&'a self, ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(&'a self, ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method with self is polled. + async fn bar_async(&'a self, ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(&'a self, ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// with self is polled. + async fn baz_async(&'a self, (ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync(&'a self, (ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method with self is polled. + async fn foobar_async( + &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync( + &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let _ = fut.as_mut().poll(&mut cx); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())), + |l| bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods w/out self (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())), + |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + Foo::foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + Foo::foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods (see doc comment on function for what it tests). + let b = Bar(Default::default()); + assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())), + |l| b.bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| b.baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + b.foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + b.foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); +} diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.rs b/src/test/ui/async-await/drop-order-locals-are-hidden.rs index 10dc5e27f6f..bcdb8878eb5 100644 --- a/src/test/ui/async-await/drop-order-locals-are-hidden.rs +++ b/src/test/ui/async-await/drop-order-locals-are-hidden.rs @@ -8,4 +8,9 @@ async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) { assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425] } +async fn baz_async(ref mut x: u32, ref y: u32) { + assert_eq!(__arg0, 1); //~ ERROR cannot find value `__arg0` in this scope [E0425] + assert_eq!(__arg1, 2); //~ ERROR cannot find value `__arg1` in this scope [E0425] +} + fn main() {} diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.stderr b/src/test/ui/async-await/drop-order-locals-are-hidden.stderr index ca0da6b7c96..484e1f4f426 100644 --- a/src/test/ui/async-await/drop-order-locals-are-hidden.stderr +++ b/src/test/ui/async-await/drop-order-locals-are-hidden.stderr @@ -10,6 +10,18 @@ error[E0425]: cannot find value `__arg2` in this scope LL | assert_eq!(__arg2, 4); | ^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0425]: cannot find value `__arg0` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:12:16 + | +LL | assert_eq!(__arg0, 1); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `__arg1` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:13:16 + | +LL | assert_eq!(__arg1, 2); + | ^^^^^^ not found in this scope + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/async-await/mutable-arguments.rs b/src/test/ui/async-await/mutable-arguments.rs deleted file mode 100644 index 4d6dba74097..00000000000 --- a/src/test/ui/async-await/mutable-arguments.rs +++ /dev/null @@ -1,10 +0,0 @@ -// edition:2018 -// run-pass - -#![feature(async_await)] - -async fn foo(n: u32, mut vec: Vec) { - vec.push(n); -} - -fn main() {} diff --git a/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs new file mode 100644 index 00000000000..c4f3f3edc48 --- /dev/null +++ b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.rs @@ -0,0 +1,36 @@ +#![feature(async_await, await_macro)] +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod await { //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this was previously accepted by the compiler + pub struct await; //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this was previously accepted by the compiler + } +} +use outer_mod::await::await; //~ ERROR `await` is a keyword in the 2018 edition +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler +//~^^^ WARN this was previously accepted by the compiler + +struct Foo { await: () } +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler + +impl Foo { fn await() {} } +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler + +macro_rules! await { +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this was previously accepted by the compiler + () => {} +} + +fn main() { + match await { await => {} } //~ ERROR `await` is a keyword in the 2018 edition + //~^ ERROR `await` is a keyword in the 2018 edition + //~^^ WARN this was previously accepted by the compiler + //~^^^ WARN this was previously accepted by the compiler +} diff --git a/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr new file mode 100644 index 00000000000..067ecd6a513 --- /dev/null +++ b/src/test/ui/await-keyword/2015-edition-error-in-non-macro-position.stderr @@ -0,0 +1,88 @@ +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:6:13 + | +LL | pub mod await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | +note: lint level defined here + --> $DIR/2015-edition-error-in-non-macro-position.rs:3:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:8:20 + | +LL | pub struct await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:12:16 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:12:23 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:17:14 + | +LL | struct Foo { await: () } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:21:15 + | +LL | impl Foo { fn await() {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:25:14 + | +LL | macro_rules! await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:32:11 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-in-non-macro-position.rs:32:19 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs b/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs deleted file mode 100644 index 92c60e7d6ee..00000000000 --- a/src/test/ui/await-keyword/2015-edition-no-warnings-with-feature-gate.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-pass - -#![feature(async_await)] -#![allow(non_camel_case_types)] -#![deny(keyword_idents)] - -mod outer_mod { - pub mod await { - pub struct await; - } -} -use outer_mod::await::await; - -fn main() { - match await { await => {} } -} diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs new file mode 100644 index 00000000000..b2e8e4be172 --- /dev/null +++ b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -0,0 +1,27 @@ +// edition:2018 + +#![allow(non_camel_case_types)] +#![feature(async_await, await_macro)] + +mod outer_mod { + pub mod await { //~ ERROR expected identifier, found reserved keyword `await` + pub struct await; //~ ERROR expected identifier, found reserved keyword `await` + } +} +use self::outer_mod::await::await; //~ ERROR expected identifier, found reserved keyword `await` +//~^ ERROR expected identifier, found reserved keyword `await` + +struct Foo { await: () } +//~^ ERROR expected identifier, found reserved keyword `await` + +impl Foo { fn await() {} } +//~^ ERROR expected identifier, found reserved keyword `await` + +macro_rules! await { +//~^ ERROR expected identifier, found reserved keyword `await` + () => {} +} + +fn main() { + match await { await => () } //~ ERROR expected `!`, found `{` +} diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr new file mode 100644 index 00000000000..076a31bd9ce --- /dev/null +++ b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr @@ -0,0 +1,80 @@ +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:7:13 + | +LL | pub mod await { + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub mod r#await { + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:8:20 + | +LL | pub struct await; + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub struct r#await; + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:11:22 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use self::outer_mod::r#await::await; + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:11:29 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use self::outer_mod::await::r#await; + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:14:14 + | +LL | struct Foo { await: () } + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | struct Foo { r#await: () } + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:17:15 + | +LL | impl Foo { fn await() {} } + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | impl Foo { fn r#await() {} } + | ^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:20:14 + | +LL | macro_rules! await { + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | macro_rules! r#await { + | ^^^^^^^ + +error: expected `!`, found `{` + --> $DIR/2018-edition-error-in-non-macro-position.rs:26:17 + | +LL | match await { await => () } + | ----- ^ expected `!` + | | + | while parsing this match expression + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/await-keyword/2018-edition-error.rs b/src/test/ui/await-keyword/2018-edition-error.rs index 7ba3382ddf1..e0b2962ce97 100644 --- a/src/test/ui/await-keyword/2018-edition-error.rs +++ b/src/test/ui/await-keyword/2018-edition-error.rs @@ -2,14 +2,13 @@ #![allow(non_camel_case_types)] mod outer_mod { - pub mod await { //~ ERROR `await` is a keyword - pub struct await; //~ ERROR `await` is a keyword + pub mod await { //~ ERROR expected identifier + pub struct await; //~ ERROR expected identifier } } -use self::outer_mod::await::await; //~ ERROR `await` is a keyword - //~^ ERROR `await` is a keyword +use self::outer_mod::await::await; //~ ERROR expected identifier + //~^ ERROR expected identifier, found reserved keyword `await` fn main() { - match await { await => () } //~ ERROR `await` is a keyword - //~^ ERROR `await` is a keyword + match await { await => () } //~ ERROR expected `!`, found `{` } diff --git a/src/test/ui/await-keyword/2018-edition-error.stderr b/src/test/ui/await-keyword/2018-edition-error.stderr index 67ff6c5675a..c8bf9b42ca5 100644 --- a/src/test/ui/await-keyword/2018-edition-error.stderr +++ b/src/test/ui/await-keyword/2018-edition-error.stderr @@ -1,38 +1,50 @@ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:5:13 | LL | pub mod await { - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub mod r#await { + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:6:20 | LL | pub struct await; - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub struct r#await; + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:9:22 | LL | use self::outer_mod::await::await; - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use self::outer_mod::r#await::await; + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition +error: expected identifier, found reserved keyword `await` --> $DIR/2018-edition-error.rs:9:29 | LL | use self::outer_mod::await::await; - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` - -error[E0721]: `await` is a keyword in the 2018 edition - --> $DIR/2018-edition-error.rs:13:11 + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers | -LL | match await { await => () } - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` +LL | use self::outer_mod::await::r#await; + | ^^^^^^^ -error[E0721]: `await` is a keyword in the 2018 edition - --> $DIR/2018-edition-error.rs:13:19 +error: expected `!`, found `{` + --> $DIR/2018-edition-error.rs:13:17 | LL | match await { await => () } - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ----- ^ expected `!` + | | + | while parsing this match expression -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs b/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs deleted file mode 100644 index 52d32c83510..00000000000 --- a/src/test/ui/await-keyword/2018-edition-no-error-with-feature-gate.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-pass -// edition:2018 - -#![allow(non_camel_case_types)] -#![feature(async_await)] - -mod outer_mod { - pub mod await { - pub struct await; - } -} -use self::outer_mod::await::await; - -fn main() { - match await { await => () } -} diff --git a/src/test/ui/await-keyword/post_expansion_error.rs b/src/test/ui/await-keyword/post_expansion_error.rs index 96dd48052de..b4c899b0d02 100644 --- a/src/test/ui/await-keyword/post_expansion_error.rs +++ b/src/test/ui/await-keyword/post_expansion_error.rs @@ -6,5 +6,5 @@ macro_rules! r#await { fn main() { await!() - //~^ ERROR `await` is a keyword + //~^ ERROR expected expression, found `)` } diff --git a/src/test/ui/await-keyword/post_expansion_error.stderr b/src/test/ui/await-keyword/post_expansion_error.stderr index 9483f774227..0996c38b3b6 100644 --- a/src/test/ui/await-keyword/post_expansion_error.stderr +++ b/src/test/ui/await-keyword/post_expansion_error.stderr @@ -1,8 +1,8 @@ -error[E0721]: `await` is a keyword in the 2018 edition - --> $DIR/post_expansion_error.rs:8:5 +error: expected expression, found `)` + --> $DIR/post_expansion_error.rs:8:12 | LL | await!() - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | ^ expected expression error: aborting due to previous error diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.rs b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs new file mode 100644 index 00000000000..54981b77a2b --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs @@ -0,0 +1,14 @@ +// Test that a concrete const type i.e. A<2>, can be used as an argument type in a function +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct A; // ok + +fn with_concrete_const_arg(_: A<2>) -> u32 { 17 } + +fn main() { + let val: A<2> = A; + assert_eq!(with_concrete_const_arg(val), 17); +} diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr new file mode 100644 index 00000000000..955b319d700 --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/concrete-const-as-fn-arg.rs:4:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/concrete-const-impl-method.rs b/src/test/ui/const-generics/concrete-const-impl-method.rs new file mode 100644 index 00000000000..226ea415180 --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-impl-method.rs @@ -0,0 +1,24 @@ +// Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>, +// is callable. +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub struct A; + +impl A<2> { + fn impl_method(&self) -> u32 { + 17 + } + + fn associated_non_method() -> u32 { + 17 + } +} + +fn main() { + let val: A<2> = A; + assert_eq!(val.impl_method(), 17); + assert_eq!(A::<2>::associated_non_method(), 17); +} diff --git a/src/test/ui/const-generics/concrete-const-impl-method.stderr b/src/test/ui/const-generics/concrete-const-impl-method.stderr new file mode 100644 index 00000000000..3ce488c6275 --- /dev/null +++ b/src/test/ui/const-generics/concrete-const-impl-method.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/concrete-const-impl-method.rs:5:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs index 662c7b767ba..22c6c351622 100644 --- a/src/test/ui/const-generics/const-expression-parameter.rs +++ b/src/test/ui/const-generics/const-expression-parameter.rs @@ -6,7 +6,7 @@ fn i32_identity() -> i32 { } fn foo_a() { - i32_identity::<-1>(); //~ ERROR expected identifier, found `<-` + i32_identity::<-1>(); // ok } fn foo_b() { diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr index 2f7a80f0c8f..c255127c280 100644 --- a/src/test/ui/const-generics/const-expression-parameter.stderr +++ b/src/test/ui/const-generics/const-expression-parameter.stderr @@ -1,9 +1,3 @@ -error: expected identifier, found `<-` - --> $DIR/const-expression-parameter.rs:9:19 - | -LL | i32_identity::<-1>(); - | ^^ expected identifier - error: expected one of `,` or `>`, found `+` --> $DIR/const-expression-parameter.rs:13:22 | @@ -16,5 +10,5 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/const-generics/issue-60263.rs b/src/test/ui/const-generics/issue-60263.rs new file mode 100644 index 00000000000..70cbc242c41 --- /dev/null +++ b/src/test/ui/const-generics/issue-60263.rs @@ -0,0 +1,9 @@ +struct B; //~ ERROR const generics are unstable + +impl B<0> { + fn bug() -> Self { + panic!() + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issue-60263.stderr b/src/test/ui/const-generics/issue-60263.stderr new file mode 100644 index 00000000000..ab1b9e4a7cd --- /dev/null +++ b/src/test/ui/const-generics/issue-60263.stderr @@ -0,0 +1,12 @@ +error[E0658]: const generics are unstable + --> $DIR/issue-60263.rs:1:16 + | +LL | struct B; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add #![feature(const_generics)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr index 603efe449f1..e45ce65d8bb 100644 --- a/src/test/ui/consts/const-eval/unused-broken-const.stderr +++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr @@ -1,5 +1,3 @@ -warning: due to multiple output types requested, the explicitly specified output file name will be adapted for each output type - error: any use of this value will cause an error --> $DIR/unused-broken-const.rs:5:18 | diff --git a/src/test/ui/emit-artifact-notifications.nll.stderr b/src/test/ui/emit-artifact-notifications.nll.stderr new file mode 100644 index 00000000000..347d9aeac23 --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.nll.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"} diff --git a/src/test/ui/emit-artifact-notifications.rs b/src/test/ui/emit-artifact-notifications.rs new file mode 100644 index 00000000000..c2c930c8b1b --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.rs @@ -0,0 +1,6 @@ +// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications +// compile-pass + +// A very basic test for the emission of artifact notifications in JSON output. + +fn main() {} diff --git a/src/test/ui/emit-artifact-notifications.stderr b/src/test/ui/emit-artifact-notifications.stderr new file mode 100644 index 00000000000..56c977181ff --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"} diff --git a/src/test/ui/emit-directives.rs b/src/test/ui/emit-directives.rs deleted file mode 100644 index 088280e358a..00000000000 --- a/src/test/ui/emit-directives.rs +++ /dev/null @@ -1,12 +0,0 @@ -// ignore-tidy-linelength -// compile-flags:--emit=metadata --error-format=json -Z emit-directives -// compile-pass -// -// Normalization is required to eliminated minor path and filename differences -// across platforms. -// normalize-stderr-test: "metadata file written: .*/emit-directives" -> "metadata file written: .../emit-directives" -// normalize-stderr-test: "emit-directives(\.\w*)?/a(\.\w*)?" -> "emit-directives/a" - -// A very basic test for the emission of build directives in JSON output. - -fn main() {} diff --git a/src/test/ui/emit-directives.stderr b/src/test/ui/emit-directives.stderr deleted file mode 100644 index b8a4b96f4bf..00000000000 --- a/src/test/ui/emit-directives.stderr +++ /dev/null @@ -1 +0,0 @@ -{"directive":"metadata file written: .../emit-directives/a"} diff --git a/src/test/ui/feature-gate/await-macro.rs b/src/test/ui/feature-gate/await-macro.rs new file mode 100644 index 00000000000..291db9ba413 --- /dev/null +++ b/src/test/ui/feature-gate/await-macro.rs @@ -0,0 +1,12 @@ +// gate-test-await_macro +// edition:2018 + +#![feature(async_await)] + +async fn bar() {} + +async fn foo() { + await!(bar()); //~ ERROR `await!()` macro syntax is unstable, and will soon be removed +} + +fn main() {} diff --git a/src/test/ui/feature-gate/await-macro.stderr b/src/test/ui/feature-gate/await-macro.stderr new file mode 100644 index 00000000000..b6833655f6d --- /dev/null +++ b/src/test/ui/feature-gate/await-macro.stderr @@ -0,0 +1,12 @@ +error[E0658]: `await!()` macro syntax is unstable, and will soon be removed in favor of `.await` syntax. + --> $DIR/await-macro.rs:9:5 + | +LL | await!(bar()); + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/50547 + = help: add #![feature(await_macro)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator-yielding-or-returning-itself.rs index 30788e3c186..fd526679818 100644 --- a/src/test/ui/generator-yielding-or-returning-itself.rs +++ b/src/test/ui/generator-yielding-or-returning-itself.rs @@ -13,7 +13,7 @@ pub fn want_cyclic_generator_return(_: T) fn supply_cyclic_generator_return() { want_cyclic_generator_return(|| { - //~^ ERROR type mismatch + //~^ ERROR closure/generator type that references itself if false { yield None.unwrap(); } None.unwrap() }) diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr index 5834aed2450..42591683fe4 100644 --- a/src/test/ui/generator-yielding-or-returning-itself.stderr +++ b/src/test/ui/generator-yielding-or-returning-itself.stderr @@ -1,20 +1,17 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]` - --> $DIR/generator-yielding-or-returning-itself.rs:15:5 +error[E0644]: closure/generator type that references itself + --> $DIR/generator-yielding-or-returning-itself.rs:15:34 | -LL | want_cyclic_generator_return(|| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size +LL | want_cyclic_generator_return(|| { + | __________________________________^ +LL | | +LL | | if false { yield None.unwrap(); } +LL | | None.unwrap() +LL | | }) + | |_____^ cyclic type of infinite size | = note: closures cannot capture themselves or take themselves as argument; this error may be the result of a recent compiler bug-fix, see https://github.com/rust-lang/rust/issues/46062 for more details -note: required by `want_cyclic_generator_return` - --> $DIR/generator-yielding-or-returning-itself.rs:9:1 - | -LL | / pub fn want_cyclic_generator_return(_: T) -LL | | where T: Generator -LL | | { -LL | | } - | |_^ error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]` --> $DIR/generator-yielding-or-returning-itself.rs:28:5 @@ -36,4 +33,5 @@ LL | | } error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0644. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs new file mode 100644 index 00000000000..b9c6bc5d079 --- /dev/null +++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs @@ -0,0 +1,17 @@ +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn foo() -> impl Generator { + || { + if false { + return Ok(6); //~ ERROR mismatched types [E0308] + } + + yield (); + + 5 + } +} + +fn main() {} diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr new file mode 100644 index 00000000000..35d3f95c3e9 --- /dev/null +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-signature-deduction.rs:8:20 + | +LL | return Ok(6); + | ^^^^^ expected i32, found enum `std::result::Result` + | + = note: expected type `i32` + found type `std::result::Result<{integer}, _>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/unresolved_type_param.rs b/src/test/ui/generator/unresolved_type_param.rs index f49369b125f..77174b03217 100644 --- a/src/test/ui/generator/unresolved_type_param.rs +++ b/src/test/ui/generator/unresolved_type_param.rs @@ -2,13 +2,14 @@ // Error message should pinpoint the type parameter T as needing to be bound // (rather than give a general error message) // edition:2018 -#![feature(futures_api, async_await, await_macro)] +#![feature(async_await)] async fn bar() -> () {} async fn foo() { - await!(bar()); - //~^ ERROR type inside generator must be known in this context - //~| NOTE cannot infer type for `T` - //~| NOTE the type is part of the generator because of this `yield` + bar().await; + //~^ ERROR type inside generator must be known in this context + //~| NOTE cannot infer type for `T` + //~| NOTE the type is part of the generator because of this `yield` + //~| NOTE in this expansion of desugaring of `await` } fn main() {} diff --git a/src/test/ui/generator/unresolved_type_param.stderr b/src/test/ui/generator/unresolved_type_param.stderr index 57ccdda3f43..afb9adf4c77 100644 --- a/src/test/ui/generator/unresolved_type_param.stderr +++ b/src/test/ui/generator/unresolved_type_param.stderr @@ -1,15 +1,14 @@ error[E0698]: type inside generator must be known in this context - --> $DIR/unresolved_type_param.rs:9:16 + --> $DIR/unresolved_type_param.rs:9:5 | -LL | await!(bar()); - | ^^^ cannot infer type for `T` +LL | bar().await; + | ^^^ cannot infer type for `T` | note: the type is part of the generator because of this `yield` - --> $DIR/unresolved_type_param.rs:9:9 + --> $DIR/unresolved_type_param.rs:9:5 | -LL | await!(bar()); - | ^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +LL | bar().await; + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51719.rs b/src/test/ui/issues/issue-51719.rs new file mode 100644 index 00000000000..2c02ac01142 --- /dev/null +++ b/src/test/ui/issues/issue-51719.rs @@ -0,0 +1,11 @@ +// edition:2018 +// +// Tests that the .await syntax can't be used to make a generator + +#![feature(async_await)] + +async fn foo() {} + +fn make_generator() { + let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/src/test/ui/issues/issue-51719.stderr b/src/test/ui/issues/issue-51719.stderr new file mode 100644 index 00000000000..768909b66ec --- /dev/null +++ b/src/test/ui/issues/issue-51719.stderr @@ -0,0 +1,8 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-51719.rs:10:19 + | +LL | let _gen = || foo.await; + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-51751.rs b/src/test/ui/issues/issue-51751.rs new file mode 100644 index 00000000000..7afd7ecc826 --- /dev/null +++ b/src/test/ui/issues/issue-51751.rs @@ -0,0 +1,13 @@ +// edition:2018 + +#![feature(async_await)] + +async fn inc(limit: i64) -> i64 { + limit + 1 +} + +fn main() { + let result = inc(10000); + let finished = result.await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/src/test/ui/issues/issue-51751.stderr b/src/test/ui/issues/issue-51751.stderr new file mode 100644 index 00000000000..0c4cb034a93 --- /dev/null +++ b/src/test/ui/issues/issue-51751.stderr @@ -0,0 +1,8 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-51751.rs:11:20 + | +LL | let finished = result.await; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs index 46c083f9305..3e9f612a2af 100644 --- a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs @@ -1,5 +1,8 @@ // compile-pass +// FIXME(eddyb) shorten the name so windows doesn't choke on it. +#![crate_name = "trait_test"] + // Regression test related to #56288. Check that a supertrait projection (of // `Output`) that references `Self` is ok if there is another occurence of // the same supertrait that specifies the projection explicitly, even if diff --git a/src/tools/cargo b/src/tools/cargo index beb8fcb5248..759b6161a32 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit beb8fcb5248dc2e6aa488af9613216d5ccb31c6a +Subproject commit 759b6161a328db1d4863139e90875308ecd25a75 diff --git a/src/tools/clippy b/src/tools/clippy index fc96aa03688..341c96afd33 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit fc96aa036884183ddc68d2659f4633e6f138b4e0 +Subproject commit 341c96afd331195beeb001436535c1feb479ff9d diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fb6ada89171..54e9b76a21e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -305,6 +305,9 @@ pub struct TestProps { pub extern_private: Vec, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, + // Environment variables to unset prior to compiling. + // Variables are unset before applying 'rustc_env'. + pub unset_rustc_env: Vec, // Environment settings to use during execution pub exec_env: Vec<(String, String)>, // Lines to check if they appear in the expected debugger output @@ -373,6 +376,7 @@ pub fn new() -> Self { extern_private: vec![], revisions: vec![], rustc_env: vec![], + unset_rustc_env: vec![], exec_env: vec![], check_lines: vec![], build_aux_docs: false, @@ -499,6 +503,10 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) { self.rustc_env.push(ee); } + if let Some(ev) = config.parse_name_value_directive(ln, "unset-rustc-env") { + self.unset_rustc_env.push(ev); + } + if let Some(cl) = config.parse_check_line(ln) { self.check_lines.push(cl); } diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 26a3c4dee40..d651b9a92b6 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -4,7 +4,7 @@ use crate::errors::{Error, ErrorKind}; use crate::runtest::ProcRes; use serde_json; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::FromStr; #[derive(Deserialize)] @@ -18,9 +18,9 @@ struct Diagnostic { } #[derive(Deserialize)] -struct Directive { +struct ArtifactNotification { #[allow(dead_code)] - directive: String, + artifact: PathBuf, } #[derive(Deserialize, Clone)] @@ -75,8 +75,8 @@ pub fn extract_rendered(output: &str) -> String { if line.starts_with('{') { if let Ok(diagnostic) = serde_json::from_str::(line) { diagnostic.rendered - } else if let Ok(_directive) = serde_json::from_str::(line) { - // Swallow the directive. + } else if let Ok(_) = serde_json::from_str::(line) { + // Ignore the notification. None } else { print!( diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 42f9cdb7886..a11a4f17eb5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1422,10 +1422,21 @@ fn is_unexpected_compiler_message( } fn compile_test(&self) -> ProcRes { - let mut rustc = self.make_compile_args( - &self.testpaths.file, - TargetLocation::ThisFile(self.make_exe_name()), - ); + // Only use `make_exe_name` when the test ends up being executed. + let will_execute = match self.config.mode { + RunPass | Ui => self.should_run_successfully(), + Incremental => self.revision.unwrap().starts_with("r"), + RunFail | RunPassValgrind | MirOpt | + DebugInfoBoth | DebugInfoGdb | DebugInfoLldb => true, + _ => false, + }; + let output_file = if will_execute { + TargetLocation::ThisFile(self.make_exe_name()) + } else { + TargetLocation::ThisDirectory(self.output_base_dir()) + }; + + let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); rustc.arg("-L").arg(&self.aux_output_dir_name()); @@ -1692,6 +1703,9 @@ fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> add_extern_priv(&private_lib, true); } + self.props.unset_rustc_env.clone() + .iter() + .fold(&mut rustc, |rustc, v| rustc.env_remove(v)); rustc.envs(self.props.rustc_env.clone()); self.compose_and_run( rustc, @@ -1882,7 +1896,12 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C rustc.arg("-o").arg(path); } TargetLocation::ThisDirectory(path) => { - rustc.arg("--out-dir").arg(path); + if is_rustdoc { + // `rustdoc` uses `-o` for the output directory. + rustc.arg("-o").arg(path); + } else { + rustc.arg("--out-dir").arg(path); + } } } @@ -3138,42 +3157,40 @@ fn get_mir_dump_dir(&self) -> PathBuf { } fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { - let parent_dir = self.testpaths.file.parent().unwrap(); let cflags = self.props.compile_flags.join(" "); let json = cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") || cflags.contains("--error-format=pretty-json"); - let parent_dir_str = if json { - parent_dir.display().to_string().replace("\\", "\\\\") - } else { - parent_dir.display().to_string() + + let mut normalized = output.to_string(); + + let mut normalize_path = |from: &Path, to: &str| { + let mut from = from.display().to_string(); + if json { + from = from.replace("\\", "\\\\"); + } + normalized = normalized.replace(&from, to); }; - let mut normalized = output.replace(&parent_dir_str, "$DIR"); + let parent_dir = self.testpaths.file.parent().unwrap(); + normalize_path(parent_dir, "$DIR"); // Paths into the libstd/libcore let src_dir = self.config.src_base.parent().unwrap().parent().unwrap(); - let src_dir_str = if json { - src_dir.display().to_string().replace("\\", "\\\\") - } else { - src_dir.display().to_string() - }; - normalized = normalized.replace(&src_dir_str, "$SRC_DIR"); + normalize_path(src_dir, "$SRC_DIR"); // Paths into the build directory let test_build_dir = &self.config.build_base; let parent_build_dir = test_build_dir.parent().unwrap().parent().unwrap().parent().unwrap(); // eg. /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui - normalized = normalized.replace(test_build_dir.to_str().unwrap(), "$TEST_BUILD_DIR"); + normalize_path(test_build_dir, "$TEST_BUILD_DIR"); // eg. /home/user/rust/build - normalized = normalized.replace(&parent_build_dir.to_str().unwrap(), "$BUILD_DIR"); + normalize_path(parent_build_dir, "$BUILD_DIR"); // Paths into lib directory. - let mut lib_dir = parent_build_dir.parent().unwrap().to_path_buf(); - lib_dir.push("lib"); - normalized = normalized.replace(&lib_dir.to_str().unwrap(), "$LIB_DIR"); + normalize_path(&parent_build_dir.parent().unwrap().join("lib"), "$LIB_DIR"); if json { // escaped newlines in json strings should be readable diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index f9f3623679e..637f10c5ae7 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -191,7 +191,7 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { // We allow rustc-internal features to omit a tracking issue. // To make tidy accept omitting a tracking issue, group the list of features - // without one inside `// no tracking issue START` and `// no tracking issue END`. + // without one inside `// no-tracking-issue` and `// no-tracking-issue-end`. let mut next_feature_omits_tracking_issue = false; let mut in_feature_group = false; @@ -201,13 +201,13 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { .filter_map(|(line, line_number)| { let line = line.trim(); - // Within START and END, the tracking issue can be omitted. + // Within -start and -end, the tracking issue can be omitted. match line { - "// no tracking issue START" => { + "// no-tracking-issue-start" => { next_feature_omits_tracking_issue = true; return None; } - "// no tracking issue END" => { + "// no-tracking-issue-end" => { next_feature_omits_tracking_issue = false; return None; }