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)",
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",
]
"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)",
[[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)",
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",
]
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",
]
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",
]
[[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)",
]
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)",
]
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",
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",
]
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",
]
"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",
]
"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",
]
"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",
]
"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",
]
"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)",
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)",
]
"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"
"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"
# 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
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(libc)]
-#![feature(needs_allocator)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(pattern)]
/// let mut v: Vec<i32> = 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.
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.
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
```
doc_comment! {
concat!("Return the memory representation of this integer as a byte array in
little-endian byte order.
-
+",
+$to_xe_bytes_doc,
+"
# Examples
```
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
doc_comment! {
concat!("Create an integer value from its representation as a byte array in
big endian.
-
+",
+$from_xe_bytes_doc,
+"
# Examples
```
concat!("
Create an integer value from its representation as a byte array in
little endian.
-
+",
+$from_xe_bytes_doc,
+"
# Examples
```
[`from_be_bytes`]: #method.from_be_bytes
[`from_le_bytes`]: #method.from_le_bytes
-
+",
+$from_xe_bytes_doc,
+"
# Examples
```
#[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"]
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"]
"[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")]
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")]
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.
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
```
doc_comment! {
concat!("Return the memory representation of this integer as a byte array in
little-endian byte order.
-
+",
+$to_xe_bytes_doc,
+"
# Examples
```
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
doc_comment! {
concat!("Create an integer value from its representation as a byte array in
big endian.
-
+",
+$from_xe_bytes_doc,
+"
# Examples
```
concat!("
Create an integer value from its representation as a byte array in
little endian.
-
+",
+$from_xe_bytes_doc,
+"
# Examples
```
[`from_be_bytes`]: #method.from_be_bytes
[`from_le_bytes`]: #method.from_le_bytes
-
+",
+$from_xe_bytes_doc,
+"
# Examples
```
#[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.
#[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"]
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"]
"[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")]
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.
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();
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
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
}
modules: BTreeMap<NodeId, hir::ModuleItems>,
is_generator: bool,
+ is_async_body: bool,
catch_scopes: Vec<NodeId>,
loop_scopes: Vec<NodeId>,
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,
}
fn record_body(&mut self, value: hir::Expr, arguments: HirVec<hir::Arg>) -> 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,
};
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),
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);
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;
}
})
})
}
+ 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
) => {
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::*;
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))
}
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));
}
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(
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
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(
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)]`
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);
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>,
+ ) -> 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::Expr>,
+ ) -> 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())
}
self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
}
- fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr> {
- 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>) -> hir::Expr {
+ self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new())
}
fn expr(&mut self, span: Span, node: hir::ExprKind, attrs: ThinVec<Attribute>) -> hir::Expr {
}
}
+ fn expr_unsafe(&mut self, expr: P<hir::Expr>) -> 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<hir::Pat>) -> P<hir::Pat> {
self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
}
span: Span,
components: &[&str],
params: Option<P<hir::GenericArgs>>,
- 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());
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 = <expr>;
+ // 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 = <expr>;
+ 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<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
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;
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};
source_map: &'a SourceMap,
/// The node map
- map: FxHashMap<HirId, Entry<'hir>>,
+ map: HirEntryMap<'hir>,
/// The parent of this node
parent_node: hir::HirId,
);
}
+ 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,
crate_disambiguator: CrateDisambiguator,
cstore: &dyn CrateStore,
commandline_args_hash: u64)
- -> (FxHashMap<HirId, Entry<'hir>>, Svh)
+ -> (HirEntryMap<'hir>, Svh)
{
self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
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>) {
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;
}
}
+/// This type is effectively a `HashMap<HirId, Entry<'hir>>`,
+/// 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<Option<B>>` mapping a `DefIndex`'s index to a inner value
+/// - which is `B = IndexVec<ItemLocalId, Option<Entry<'hir>>` which finally gives you the `Entry`.
+pub(super) type HirEntryMap<'hir> = [Vec<Option<IndexVec<ItemLocalId, Option<Entry<'hir>>>>>; 2];
+
/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
#[derive(Clone)]
pub struct Map<'hir> {
/// The SVH of the local crate.
pub crate_hash: Svh,
- map: FxHashMap<HirId, Entry<'hir>>,
+ map: HirEntryMap<'hir>,
definitions: &'hir Definitions,
}
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
/// 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)
})
}
- fn entry_count(&self) -> usize {
- self.map.len()
- }
-
fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
- self.map.get(&id).cloned()
+ self.lookup(id).cloned()
}
pub fn krate(&self) -> &'hir Crate {
/// 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)
}
attrs.unwrap_or(&[])
}
+ /// Returns an iterator that yields all the hir ids in the map.
+ fn all_ids<'a>(&'a self) -> impl Iterator<Item = HirId> + '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.)
///
/// 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<Item = NodeId> + '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 {
}
}
-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) {
if mod_name != &**part {
return false;
}
- cursor = self.map.get_parent(mod_id);
+ cursor = self.map.get_parent_item(mod_id);
}
return true;
// 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;
}
// 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<NodeId> {
- 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)
}
}
/// }
/// ```
AsyncFn,
+ /// A desugared `<expr>.await`.
+ AwaitDesugar,
}
/// Hints at the original code for a `match _ { .. }`.
ForLoopDesugar,
/// A desugared `?` operator.
TryDesugar,
+ /// A desugared `<expr>.await`.
+ AwaitDesugar,
}
/// The loop type that yielded an `ExprKind::Loop`.
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
Async,
+ Await,
QuestionMark,
ExistentialReturnType,
ForLoop,
use super::*;
+use crate::ty::Const;
use crate::ty::relate::{Relate, TypeRelation};
pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> {
}
}
+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,
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());
}
_ => {
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,);
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),
}
pub enum ValuePairs<'tcx> {
Types(ExpectedFound<Ty<'tcx>>),
Regions(ExpectedFound<ty::Region<'tcx>>),
+ Consts(ExpectedFound<&'tcx ty::Const<'tcx>>),
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
}
impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
(ValuePairs::Types)(a),
(ValuePairs::Regions)(a),
+ (ValuePairs::Consts)(a),
(ValuePairs::TraitRefs)(a),
(ValuePairs::PolyTraitRefs)(a),
}
the same values as the target option of the same name"),
allow_features: Option<Vec<String>> = (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 {
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
}
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(
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;
}
}
},
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))))
},
}
#[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]
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,
}
(&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)
}
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};
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)
}
}
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),
fn super_visit_with<V: TypeVisitor<'tcx>>(&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,
}
}
}
+
+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<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
+ false
+ }
+}
#[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 {
}
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
}
}
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,
}
}
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) => {
when substituting (root type={:?}) substs={:?}",
p,
source_ty,
- p.idx,
+ p.index,
kind,
self.root_ty,
self.substs,
when substituting (root type={:?}) substs={:?}",
p,
source_ty,
- p.idx,
+ p.index,
self.root_ty,
self.substs,
);
}
};
- // 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
/// 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<T: TypeFoldable<'tcx>>(&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
);
}
}
+ if sess.opts.debugging_opts.emit_artifact_notifications {
+ sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename);
+ }
}
if sess.opts.cg.save_temps {
}
}
- // 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
}
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.
//
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)?);
}
}
-enum NodesMatchingUII<'a, 'hir: 'a> {
+enum NodesMatchingUII<'a> {
NodesMatchingDirect(option::IntoIter<ast::NodeId>),
- NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'hir>),
+ NodesMatchingSuffix(Box<dyn Iterator<Item = ast::NodeId> + 'a>),
}
-impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> {
+impl<'a> Iterator for NodesMatchingUII<'a> {
type Item = ast::NodeId;
fn next(&mut self) -> Option<ast::NodeId> {
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)))
+ }
}
}
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};
/// 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 {
use std::cell::Cell;
use std::{error, fmt};
use std::panic;
+use std::path::Path;
use termcolor::{ColorSpec, Color};
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,
}
}
- 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);
}
}
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);
}
}
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};
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
// 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;
}
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 `")
// 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
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.
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 => {}
}
}
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;
}
// 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"),
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);
//
// 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::<u32>().and_then(|a| b.parse::<u32>().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
.. 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::<u32>().and_then(|a| b.parse::<u32>().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
+}
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(),
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(),
}
/// Given a projection like "<F as Fn(X)>::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
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::<Vec<_>>(),
+ _ => 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 })
}
});
}
- 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
ty
);
- // FIXME(const_generics): we probably want to check the bounds for const parameters too.
-
if own_counts.types == 0 {
return;
}
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.
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)
}
pub struct Parameter(pub u32);
impl From<ty::ParamTy> for Parameter {
- fn from(param: ty::ParamTy) -> Self { Parameter(param.idx) }
+ fn from(param: ty::ParamTy) -> Self { Parameter(param.index) }
}
impl From<ty::EarlyBoundRegion> for Parameter {
}
ty::Param(ref data) => {
- self.add_constraint(current, data.idx, variance);
+ self.add_constraint(current, data.index, variance);
}
ty::FnPtr(sig) => {
}
Some(param.clean(cx))
}
- ty::GenericParamDefKind::Const { .. } => {
- unimplemented!() // FIXME(const_generics)
- }
+ ty::GenericParamDefKind::Const { .. } => None,
}).collect::<Vec<GenericParamDef>>();
let mut where_predicates = preds.predicates.iter()
height: 45px;
}
+ .rustdoc.source > .sidebar > .sidebar-menu {
+ display: none;
+ }
+
.sidebar-elems {
position: fixed;
z-index: 1;
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<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
self.to_str().unwrap().encode(e)
}
}
+impl Encodable for path::PathBuf {
+ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+ path::Path::encode(self, e)
+ }
+}
+
impl Decodable for path::PathBuf {
fn decode<D: Decoder>(d: &mut D) -> Result<path::PathBuf, D::Error> {
let bytes: String = Decodable::decode(d)?;
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'] }
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,
/// created during lowering cannot be made the parent of any other
/// preexisting defs.
Async(CaptureBy, NodeId, P<Block>),
+ /// An await expression (`my_future.await`).
+ Await(AwaitOrigin, P<Expr>),
+
/// A try block (`try { ... }`).
TryBlock(P<Block>),
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<Mac_>;
/// Represents a macro invocation. The `Path` indicates which macro
// 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.
// 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),
// 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),
// 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),
// 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),
// 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),
// 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)),
// 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),
];
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
(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)]`")),
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,
(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! (
);
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),
// 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.
(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
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!(<expr>)` macro syntax is unstable, and will soon be removed \
+ in favor of `<expr>.await` syntax."
+ ),
+ }
+ }
_ => {}
}
visit::walk_expr(self, e);
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};
}
}
- 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);
}
}
}
}
#[derive(RustcEncodable)]
-struct Directive {
- /// The directive itself.
- directive: String,
+struct ArtifactNotification<'a> {
+ /// The path of the artifact.
+ artifact: &'a Path,
}
impl Diagnostic {
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);
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...
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 {
abi,
asyncness,
},
- decl: d,
+ decl,
};
let body = match self.token {
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| {
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)?;
// Assuming we have just parsed `.`, continue parsing into an expression.
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
+ 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));
});
assoc_ty_bindings.push(span);
} else if self.check_const_arg() {
- // FIXME(const_generics): to distinguish between idents for types and consts,
- // we should introduce a GenericArg::Ident in the AST and distinguish when
- // lowering to the HIR. For now, idents for const args are not permitted.
-
// Parse const argument.
let expr = if let token::OpenDelim(token::Brace) = self.token {
self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
self.fatal("identifiers may currently not be used for const generics")
);
} else {
- // FIXME(const_generics): this currently conflicts with emplacement syntax
- // with negative integer literals.
self.parse_literal_maybe_minus()?
};
let value = AnonConst {
-> 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)))
}
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 };
///
/// 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<IsAsync>, decl: &FnDecl) {
+ fn construct_async_arguments(&mut self, asyncness: &mut Spanned<IsAsync>, 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;
// `let <pat> = __argN;` statement, instead just adding a `let <pat> = <pat>;`
// 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: <ty>` to replace the argument of the
})
};
+ // 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 });
}
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(),
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)?;
TryBlock,
Struct,
Async,
+ Await,
Err,
}
ExprPrecedence::Unary => PREC_PREFIX,
// Unary, postfix
+ ExprPrecedence::Await |
ExprPrecedence::Call |
ExprPrecedence::MethodCall |
ExprPrecedence::Field |
// 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, _) |
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);
/// `impl Trait` with `Foo`.
ExistentialReturnType,
Async,
+ Await,
ForLoop,
}
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",
// 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
--- /dev/null
+//
+// 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 }
+}
--- /dev/null
+//
+// 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 }
+}
--- /dev/null
+//
+// 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 }
+}
--- /dev/null
+//
+// 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 }
+}
$(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
--- /dev/null
+extern crate bar;
+
+fn main() {}
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");
+}
// edition:2018
// aux-build:arc_wake.rs
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
extern crate arc_wake;
fn async_block(x: u8) -> impl Future<Output = u8> {
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<Output = u8> + 'a {
async move {
- await!(wake_and_yield_once());
+ wake_and_yield_once().await;
*x
}
}
fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
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<Output = u8> {
(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<T>(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<Output = u8> + 'a {
async move {
- await!(wake_and_yield_once());
+ wake_and_yield_once().await;
*x
}
}
*/
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<Output = u8> {
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
}
impl Foo {
async fn async_method(x: u8) -> u8 {
unsafe {
- await!(unsafe_async_fn(x))
+ unsafe_async_fn(x).await
}
}
}
($($fn_name:expr,)*) => { $(
test_future_yields_once_then_returns(|x| {
async move {
- await!($fn_name(&x))
+ $fn_name(&x).await
}
});
)* }
Foo::async_method,
|x| {
async move {
- unsafe { await!(unsafe_async_fn(x)) }
+ unsafe { unsafe_async_fn(x).await }
}
},
}
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
}
},
}
--- /dev/null
+// 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>) {
+ Self::wake_by_ref(&self)
+ }
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ 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<Output = u8> {
+ async move {
+ await!(wake_and_yield_once());
+ x
+ }
+}
+
+fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
+ async move {
+ await!(wake_and_yield_once());
+ *x
+ }
+}
+
+fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
+ async move {
+ let future = async {
+ await!(wake_and_yield_once());
+ x
+ };
+ await!(future)
+ }
+}
+
+fn async_closure(x: u8) -> impl Future<Output = u8> {
+ (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<T>(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<Output = u8> + '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<Output = u8> {
+ 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, Fut>(f: F)
+where
+ F: FnOnce(u8) -> Fut,
+ Fut: Future<Output = u8>,
+{
+ 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))
+ }
+ },
+ }
+}
--- /dev/null
+// 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();
+}
// edition:2018
// run-pass
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
trait Foo { }
}
async fn bad<T>(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() {
--- /dev/null
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+#![deny(unused_mut)]
+#![feature(async_await)]
+
+type A = Vec<u32>;
+
+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() {}
--- /dev/null
+// 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<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+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<Fut: Future<Output = ()>>(
+ 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()),
+ )
+ },
+ );
+}
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() {}
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`.
+++ /dev/null
-// edition:2018
-// run-pass
-
-#![feature(async_await)]
-
-async fn foo(n: u32, mut vec: Vec<u32>) {
- vec.push(n);
-}
-
-fn main() {}
--- /dev/null
+#![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
+}
--- /dev/null
+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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 9 previous errors
+
+++ /dev/null
-// 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 => {} }
-}
--- /dev/null
+// 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 `{`
+}
--- /dev/null
+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
+
#![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 `{`
}
-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
+++ /dev/null
-// 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 => () }
-}
fn main() {
await!()
- //~^ ERROR `await` is a keyword
+ //~^ ERROR expected expression, found `)`
}
-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
--- /dev/null
+// 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<const N: usize>; // 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);
+}
--- /dev/null
+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)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// 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<const N: u32>;
+
+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);
+}
--- /dev/null
+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)]
+ | ^^^^^^^^^^^^^^
+
}
fn foo_a() {
- i32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
+ i32_identity::<-1>(); // ok
}
fn foo_b() {
-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
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error
--- /dev/null
+struct B<const I: u8>; //~ ERROR const generics are unstable
+
+impl B<0> {
+ fn bug() -> Self {
+ panic!()
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0658]: const generics are unstable
+ --> $DIR/issue-60263.rs:1:16
+ |
+LL | struct B<const I: u8>;
+ | ^
+ |
+ = 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`.
-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
|
--- /dev/null
+{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"}
--- /dev/null
+// 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() {}
--- /dev/null
+{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"}
+++ /dev/null
-// 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() {}
+++ /dev/null
-{"directive":"metadata file written: .../emit-directives/a"}
--- /dev/null
+// gate-test-await_macro
+// edition:2018
+
+#![feature(async_await)]
+
+async fn bar() {}
+
+async fn foo() {
+ await!(bar()); //~ ERROR `await!(<expr>)` macro syntax is unstable, and will soon be removed
+}
+
+fn main() {}
--- /dev/null
+error[E0658]: `await!(<expr>)` macro syntax is unstable, and will soon be removed in favor of `<expr>.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`.
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()
})
-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>(_: T)
-LL | | where T: Generator<Yield = (), Return = T>
-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
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`.
--- /dev/null
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn foo() -> impl Generator<Return = i32> {
+ || {
+ if false {
+ return Ok(6); //~ ERROR mismatched types [E0308]
+ }
+
+ yield ();
+
+ 5
+ }
+}
+
+fn main() {}
--- /dev/null
+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`.
// 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<T>() -> () {}
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() {}
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
--- /dev/null
+// 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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
+}
--- /dev/null
+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
+
// 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
-Subproject commit beb8fcb5248dc2e6aa488af9613216d5ccb31c6a
+Subproject commit 759b6161a328db1d4863139e90875308ecd25a75
-Subproject commit fc96aa036884183ddc68d2659f4633e6f138b4e0
+Subproject commit 341c96afd331195beeb001436535c1feb479ff9d
pub extern_private: Vec<String>,
// 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<String>,
// Environment settings to use during execution
pub exec_env: Vec<(String, String)>,
// Lines to check if they appear in the expected debugger output
extern_private: vec![],
revisions: vec![],
rustc_env: vec![],
+ unset_rustc_env: vec![],
exec_env: vec![],
check_lines: vec![],
build_aux_docs: false,
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);
}
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)]
}
#[derive(Deserialize)]
-struct Directive {
+struct ArtifactNotification {
#[allow(dead_code)]
- directive: String,
+ artifact: PathBuf,
}
#[derive(Deserialize, Clone)]
if line.starts_with('{') {
if let Ok(diagnostic) = serde_json::from_str::<Diagnostic>(line) {
diagnostic.rendered
- } else if let Ok(_directive) = serde_json::from_str::<Directive>(line) {
- // Swallow the directive.
+ } else if let Ok(_) = serde_json::from_str::<ArtifactNotification>(line) {
+ // Ignore the notification.
None
} else {
print!(
}
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());
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,
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);
+ }
}
}
}
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
// 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;
.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;
}