From: bors Date: Sat, 22 Sep 2018 11:56:08 +0000 (+0000) Subject: Auto merge of #54265 - arielb1:civilize-proc-macros, r=alexcrichton X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=e7b5ba8661aa844a06c37f22d7af0afb1807d347;hp=1b938068b601ffa211e5503f565d082d78ebcd14;p=rust.git Auto merge of #54265 - arielb1:civilize-proc-macros, r=alexcrichton avoid leaking host details in proc macro metadata decoding proc macro crates are essentially implemented as dynamic libraries using a dlopen-based ABI. They are also Rust crates, so they have 2 worlds - the "host" world in which they are defined, and the "target" world in which they are used. For all the "target" world knows, the proc macro crate might not even be implemented in Rust, so leaks of details from the host to the target must be avoided for correctness. Because the "host" DefId space is different from the "target" DefId space, any leak involving a DefId will have a nonsensical or out-of-bounds DefKey, and will cause all sorts of crashes. This PR fixes all leaks I have found in `decoder`. In particular, #54059 was caused by host native libraries leaking into the target, which feels like it might even be a correctness issue if it doesn't cause an ICE. Fixes #54059 --- diff --git a/.travis.yml b/.travis.yml index b1701e4a654..0646f4d4687 100644 --- a/.travis.yml +++ b/.travis.yml @@ -301,7 +301,7 @@ after_failure: EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; - gdb -q -c "$CORE" "$EXE" + gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' diff --git a/src/Cargo.lock b/src/Cargo.lock index 989655ffb4f..c2c3f37db37 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -12,7 +12,7 @@ version = "0.0.0" dependencies = [ "compiler_builtins 0.0.0", "core 0.0.0", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -20,7 +20,7 @@ name = "alloc_jemalloc" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", "libc 0.0.0", @@ -112,7 +112,7 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -131,7 +131,7 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -170,18 +170,24 @@ name = "byteorder" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytesize" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cargo" -version = "0.31.0" +version = "0.32.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.19.0", + "crates-io 0.20.0", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -198,7 +204,7 @@ dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (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)", @@ -240,7 +246,7 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.22" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -356,7 +362,7 @@ name = "cmake" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -387,7 +393,7 @@ dependencies = [ name = "compiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -433,7 +439,7 @@ dependencies = [ name = "core" version = "0.0.0" dependencies = [ - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -452,9 +458,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crates-io" -version = "0.19.0" +version = "0.20.0" dependencies = [ - "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -475,7 +481,7 @@ dependencies = [ "crossbeam-epoch 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -546,10 +552,10 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -561,12 +567,13 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -808,6 +815,16 @@ name = "getopts" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "getset" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "git2" version = "0.7.5" @@ -815,7 +832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -827,7 +844,7 @@ name = "git2-curl" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1063,27 +1080,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libgit2-sys" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libnghttp2-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libssh2-sys" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1091,10 +1115,10 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1142,7 +1166,7 @@ name = "lzma-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1246,7 +1270,7 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1268,9 +1292,8 @@ dependencies = [ "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1356,7 +1379,7 @@ name = "openssl-src" version = "110.0.7+1.1.0i" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1364,7 +1387,7 @@ name = "openssl-sys" version = "0.9.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1444,7 +1467,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1571,7 +1594,7 @@ dependencies = [ name = "profiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -1644,7 +1667,7 @@ dependencies = [ [[package]] name = "rand" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1753,7 +1776,7 @@ dependencies = [ name = "rls" version = "0.130.5" dependencies = [ - "cargo 0.31.0", + "cargo 0.32.0", "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1767,6 +1790,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2084,7 +2108,7 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2173,6 +2197,7 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", @@ -2191,7 +2216,7 @@ version = "0.0.0" dependencies = [ "graphviz 0.0.0", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_fs_util 0.0.0", @@ -2217,7 +2242,7 @@ name = "rustc_llvm" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2433,6 +2458,7 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2620,14 +2646,14 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", @@ -2794,7 +2820,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3014,6 +3040,17 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vergen" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "version_check" version = "0.1.4" @@ -3122,8 +3159,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" +"checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" -"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007" +"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0" "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" @@ -3146,8 +3184,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" -"checksum curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "444c2f9e71458b34e75471ed8d756947a0bb920b8b8b9bfc56dfcc4fc6819a13" -"checksum curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "981bd902fcd8b8b999cf71b81447e27d66c3493a7f62f1372866fd32986c0c82" +"checksum curl 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c8172e96ecfb1a2bfe3843d9d7154099a15130cf4a2f658259c7aa9cc2b5d4ff" +"checksum curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2edeedbbd9c7cdccb14bfb5dfbcc108901f99d3411eb5bab3758789377c5bec4" "checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142" "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a" "checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b" @@ -3176,6 +3214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" +"checksum getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54c7f36a235738bb25904d6a2b3dbb28f6f5736cd3918c4bf80d6bb236200782" "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b502f6b1b467957403d168f0039e0c46fa6a1220efa2adaef25d5b267b5fe024" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" @@ -3201,9 +3240,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab62b46003ba97701554631fa570d9f7e7947e2480ae3d941e555a54a2c0f05" -"checksum libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "10dbc0957a27626444f5a3f523e6b97a70c3d702999bf1c7161cfbe7a25a9368" -"checksum libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "f5f9aba969b3c45fe9c94bec65895868a9ceca9a600699f4054b75747a19c7c6" +"checksum libgit2-sys 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "93f2b22fce91fb820363cf88a849a8f8fdfd8be37774b6a9dd6cbda05cf940e6" +"checksum libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ffbfb81475cc9f625e44f3a8f8b9cf7173815ae1c7cc2fa91853ec009e38198" +"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" +"checksum libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "65ff614643d7635dfa2151913d95c4ee90ee1fe15d9e0980f4dcb1a7e5837c18" "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" @@ -3262,7 +3302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4bc3847329b20ff5ba56c298938c179ae9911af15c9c10553f683b65164533" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea" +"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" @@ -3348,6 +3388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a16834fc61e1492c07dae49b6c14b55f8b1d43a5f5f9e9a2ecc063f47b9f93c" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2f7f3058b04..b842bc43f5b 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -708,6 +708,80 @@ pub fn cargo( ) -> Command { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); + + // command specific path, we call clear_if_dirty with this + let mut my_out = match cmd { + "build" => self.cargo_out(compiler, mode, target), + + // This is the intended out directory for crate documentation. + "doc" => self.crate_doc_out(target), + + _ => self.stage_out(compiler, mode), + }; + + // This is for the original compiler, but if we're forced to use stage 1, then + // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since + // we copy the libs forward. + let cmp = if self.force_use_stage1(compiler, target) { + self.compiler(1, compiler.host) + } else { + compiler + }; + + let libstd_stamp = match cmd { + "check" => check::libstd_stamp(self, cmp, target), + _ => compile::libstd_stamp(self, cmp, target), + }; + + let libtest_stamp = match cmd { + "check" => check::libtest_stamp(self, cmp, target), + _ => compile::libstd_stamp(self, cmp, target), + }; + + let librustc_stamp = match cmd { + "check" => check::librustc_stamp(self, cmp, target), + _ => compile::librustc_stamp(self, cmp, target), + }; + + if cmd == "doc" { + if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { + // This is the intended out directory for compiler documentation. + my_out = self.compiler_doc_out(target); + } + let rustdoc = self.rustdoc(compiler.host); + self.clear_if_dirty(&my_out, &rustdoc); + } else if cmd != "test" { + match mode { + Mode::Std => { + self.clear_if_dirty(&my_out, &self.rustc(compiler)); + }, + Mode::Test => { + self.clear_if_dirty(&my_out, &libstd_stamp); + }, + Mode::Rustc => { + self.clear_if_dirty(&my_out, &self.rustc(compiler)); + self.clear_if_dirty(&my_out, &libstd_stamp); + self.clear_if_dirty(&my_out, &libtest_stamp); + }, + Mode::Codegen => { + self.clear_if_dirty(&my_out, &librustc_stamp); + }, + Mode::ToolBootstrap => { }, + Mode::ToolStd => { + self.clear_if_dirty(&my_out, &libstd_stamp); + }, + Mode::ToolTest => { + self.clear_if_dirty(&my_out, &libstd_stamp); + self.clear_if_dirty(&my_out, &libtest_stamp); + }, + Mode::ToolRustc => { + self.clear_if_dirty(&my_out, &libstd_stamp); + self.clear_if_dirty(&my_out, &libtest_stamp); + self.clear_if_dirty(&my_out, &librustc_stamp); + }, + } + } + cargo .env("CARGO_TARGET_DIR", out_dir) .arg(cmd); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 20cdfcb3d29..11463c1a056 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -12,7 +12,7 @@ use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; use builder::{RunConfig, Builder, ShouldRun, Step}; -use tool::{self, prepare_tool_cargo, SourceType}; +use tool::{prepare_tool_cargo, SourceType}; use {Compiler, Mode}; use cache::{INTERNER, Interned}; use std::path::PathBuf; @@ -40,14 +40,11 @@ fn run(self, builder: &Builder) { let target = self.target; let compiler = builder.compiler(0, builder.config.build); - let out_dir = builder.stage_out(compiler, Mode::Std); - builder.clear_if_dirty(&out_dir, &builder.rustc(compiler)); - let mut cargo = builder.cargo(compiler, Mode::Std, target, "check"); std_cargo(builder, &compiler, target, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Checking std artifacts ({} -> {})", &compiler.host, target); + builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, vec![], @@ -88,15 +85,13 @@ fn run(self, builder: &Builder) { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - let stage_out = builder.stage_out(compiler, Mode::Rustc); - builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target)); - builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target)); + builder.ensure(Test { target }); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "check"); rustc_cargo(builder, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); + builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, vec![], @@ -139,8 +134,7 @@ fn run(self, builder: &Builder) { let target = self.target; let backend = self.backend; - let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target)); + builder.ensure(Rustc { target }); let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check"); cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); @@ -180,14 +174,13 @@ fn run(self, builder: &Builder) { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - let out_dir = builder.stage_out(compiler, Mode::Test); - builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target)); + builder.ensure(Std { target }); let mut cargo = builder.cargo(compiler, Mode::Test, target, "check"); test_cargo(builder, &compiler, target, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Checking test artifacts ({} -> {})", &compiler.host, target); + builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, vec![], @@ -223,10 +216,7 @@ fn run(self, builder: &Builder) { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - let stage_out = builder.stage_out(compiler, Mode::ToolRustc); - builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target)); - builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target)); - builder.clear_if_dirty(&stage_out, &librustc_stamp(builder, compiler, target)); + builder.ensure(Rustc { target }); let mut cargo = prepare_tool_cargo(builder, compiler, @@ -246,12 +236,7 @@ fn run(self, builder: &Builder) { let libdir = builder.sysroot_libdir(compiler, target); add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target)); - - builder.ensure(tool::CleanTools { - compiler, - target, - cause: Mode::Rustc, - }); + builder.cargo(compiler, Mode::ToolRustc, target, "clean"); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c0661a773e3..4205d5aebff 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -32,7 +32,6 @@ use util::{exe, libdir, is_dylib, CiEnv}; use {Compiler, Mode, GitRepo}; use native; -use tool; use cache::{INTERNER, Interned}; use builder::{Step, RunConfig, ShouldRun, Builder}; @@ -107,8 +106,6 @@ fn run(self, builder: &Builder) { copy_musl_third_party_objects(builder, target, &libdir); } - let out_dir = builder.cargo_out(compiler, Mode::Std, target); - builder.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); std_cargo(builder, &compiler, target, &mut cargo); @@ -246,11 +243,7 @@ fn run(self, builder: &Builder) { copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } - builder.ensure(tool::CleanTools { - compiler: target_compiler, - target, - cause: Mode::Std, - }); + builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); } } @@ -387,8 +380,6 @@ fn run(self, builder: &Builder) { return; } - let out_dir = builder.cargo_out(compiler, Mode::Test, target); - builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Test, target, "build"); test_cargo(builder, &compiler, target, &mut cargo); @@ -448,11 +439,8 @@ fn run(self, builder: &Builder) { target)); add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target), &libtest_stamp(builder, compiler, target)); - builder.ensure(tool::CleanTools { - compiler: target_compiler, - target, - cause: Mode::Test, - }); + + builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); } } @@ -519,9 +507,6 @@ fn run(self, builder: &Builder) { compiler: builder.compiler(self.compiler.stage, builder.config.build), target: builder.config.build, }); - let cargo_out = builder.cargo_out(compiler, Mode::Rustc, target); - builder.clear_if_dirty(&cargo_out, &libstd_stamp(builder, compiler, target)); - builder.clear_if_dirty(&cargo_out, &libtest_stamp(builder, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build"); rustc_cargo(builder, &mut cargo); @@ -613,11 +598,7 @@ fn run(self, builder: &Builder) { target)); add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target), &librustc_stamp(builder, compiler, target)); - builder.ensure(tool::CleanTools { - compiler: target_compiler, - target, - cause: Mode::Rustc, - }); + builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); } } @@ -674,7 +655,6 @@ fn run(self, builder: &Builder) { } let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - builder.clear_if_dirty(&out_dir, &librustc_stamp(builder, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc"); cargo.arg("--manifest-path") diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9a5d78e58ea..17ccb04a714 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -455,7 +455,6 @@ fn run(self, builder: &Builder) { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -480,7 +479,6 @@ fn run(self, builder: &Builder) { // This way rustdoc generates output directly into the output, and rustdoc // will also directly handle merging. let my_out = builder.crate_doc_out(target); - builder.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Std, target, "doc"); @@ -535,7 +533,6 @@ fn run(self, builder: &Builder) { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -551,7 +548,6 @@ fn run(self, builder: &Builder) { // See docs in std above for why we symlink let my_out = builder.crate_doc_out(target); - builder.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc"); @@ -603,7 +599,6 @@ fn run(self, builder: &Builder) { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -619,7 +614,6 @@ fn run(self, builder: &Builder) { // See docs in std above for why we symlink let my_out = builder.crate_doc_out(target); - builder.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); @@ -678,7 +672,6 @@ fn run(self, builder: &Builder) { // Get the correct compiler for this stage. let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -699,7 +692,6 @@ fn run(self, builder: &Builder) { // We do not symlink to the same shared folder that already contains std library // documentation from previous steps as we do not want to include that. let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc"); - builder.clear_if_dirty(&out, &rustdoc); t!(symlink_dir_force(&builder.config, &out, &out_dir)); // Build cargo command. @@ -780,7 +772,6 @@ fn run(self, builder: &Builder) { // Get the correct compiler for this stage. let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -803,7 +794,6 @@ fn run(self, builder: &Builder) { .join(target) .join("doc"); t!(fs::create_dir_all(&out_dir)); - builder.clear_if_dirty(&out, &rustdoc); t!(symlink_dir_force(&builder.config, &out, &out_dir)); // Build cargo command. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ed6a5f94d0d..6b88516bacd 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -352,6 +352,7 @@ pub enum Mode { /// Compile a tool which uses all libraries we compile (up to rustc). /// Doesn't use the stage0 compiler libraries like "other", and includes /// tools like rustdoc, cargo, rls, etc. + ToolTest, ToolStd, ToolRustc, } @@ -572,6 +573,7 @@ fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf { Mode::Codegen => "-codegen", Mode::ToolBootstrap => "-bootstrap-tools", Mode::ToolStd => "-tools", + Mode::ToolTest => "-tools", Mode::ToolRustc => "-tools", }; self.out.join(&*compiler.host) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 92665c09f72..0c4816dc904 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -755,10 +755,11 @@ fn run(self, builder: &Builder) { compare_mode: "nll" }); -default_test!(RunPass { +default_test_with_compare_mode!(RunPass { path: "src/test/run-pass", mode: "run-pass", - suite: "run-pass" + suite: "run-pass", + compare_mode: "nll" }); default_test!(CompileFail { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 04aaa970654..e5299761a15 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -19,62 +19,12 @@ use Compiler; use builder::{Step, RunConfig, ShouldRun, Builder}; use util::{exe, add_lib_path}; -use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp}; +use compile; use native; use channel::GitInfo; use cache::Interned; use toolstate::ToolState; -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct CleanTools { - pub compiler: Compiler, - pub target: Interned, - pub cause: Mode, -} - -impl Step for CleanTools { - type Output = (); - - fn should_run(run: ShouldRun) -> ShouldRun { - run.never() - } - - fn run(self, builder: &Builder) { - let compiler = self.compiler; - let target = self.target; - let cause = self.cause; - - // This is for the original compiler, but if we're forced to use stage 1, then - // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since - // we copy the libs forward. - let tools_dir = builder.stage_out(compiler, Mode::ToolRustc); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; - - for &cur_mode in &[Mode::Std, Mode::Test, Mode::Rustc] { - let stamp = match cur_mode { - Mode::Std => libstd_stamp(builder, compiler, target), - Mode::Test => libtest_stamp(builder, compiler, target), - Mode::Rustc => librustc_stamp(builder, compiler, target), - _ => panic!(), - }; - - if builder.clear_if_dirty(&tools_dir, &stamp) { - break; - } - - // If we are a rustc tool, and std changed, we also need to clear ourselves out -- our - // dependencies depend on std. Therefore, we iterate up until our own mode. - if cause == cur_mode { - break; - } - } - } -} - #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum SourceType { InTree, diff --git a/src/doc/README.md b/src/doc/README.md deleted file mode 100644 index 5f25894afd7..00000000000 --- a/src/doc/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Rust documentations - -## Building - -To generate all the docs, follow the "Building Documentation" instructions in -the README in the root of the repository. This will convert the distributed -Markdown docs to HTML and generate HTML doc for the books, 'std' and 'extra' -libraries. - -To generate HTML documentation from one source file/crate, do something like: - -~~~~text -rustdoc --output html-doc/ --output-format html ../src/libstd/path.rs -~~~~ - -(This, of course, requires a working build of the `rustdoc` tool.) - -## Additional notes - -To generate an HTML version of a doc from Markdown manually, you can do -something like: - -~~~~text -rustdoc reference.md -~~~~ - -(`reference.md` being the Rust Reference Manual.) - -An overview of how to use the `rustdoc` command is available [in the docs][1]. -Further details are available from the command line by with `rustdoc --help`. - -[1]: https://github.com/rust-lang/rust/blob/master/src/doc/rustdoc/src/what-is-rustdoc.md diff --git a/src/doc/book b/src/doc/book index cff0930664b..fa91738b663 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit cff0930664b688f1dd22aefb3d16944eb4cdbfd5 +Subproject commit fa91738b66367b6f70b078251868a071f1991ace diff --git a/src/doc/index.md b/src/doc/index.md index 11313ba99e1..b1788d8c32f 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -43,6 +43,13 @@ Rust's standard library has [extensive API documentation](std/index.html), with explanations of how to use various things, as well as example code for accomplishing various tasks. +
+
+ + +
+
+ ## The Rustc Book [The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`. diff --git a/src/doc/unstable-book/src/language-features/crate-in-paths.md b/src/doc/unstable-book/src/language-features/crate-in-paths.md deleted file mode 100644 index 9901dc1ebe3..00000000000 --- a/src/doc/unstable-book/src/language-features/crate-in-paths.md +++ /dev/null @@ -1,49 +0,0 @@ -# `crate_in_paths` - -The tracking issue for this feature is: [#44660] - -[#44660]: https://github.com/rust-lang/rust/issues/44660 - ------------------------- - -The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths -using keyword `crate`. - -This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path -in the local crate (absolute paths refer to extern crates by default in that mode), but can be -used without `feature(extern_absolute_paths)` as well. - -```rust -#![feature(crate_in_paths)] - -// Imports, `::` is added implicitly -use crate::m::f; -use crate as root; - -mod m { - pub fn f() -> u8 { 1 } - pub fn g() -> u8 { 2 } - pub fn h() -> u8 { 3 } - - // OK, visibilities implicitly add starting `::` as well, like imports - pub(in crate::m) struct S; -} - -mod n -{ - use crate::m::f; - use crate as root; - pub fn check() { - assert_eq!(f(), 1); - assert_eq!(crate::m::g(), 2); - assert_eq!(root::m::h(), 3); - } -} - -fn main() { - assert_eq!(f(), 1); - assert_eq!(crate::m::g(), 2); - assert_eq!(root::m::h(), 3); - n::check(); -} -``` diff --git a/src/doc/unstable-book/src/language-features/extern-absolute-paths.md b/src/doc/unstable-book/src/language-features/extern-absolute-paths.md deleted file mode 100644 index 6a22e7eba64..00000000000 --- a/src/doc/unstable-book/src/language-features/extern-absolute-paths.md +++ /dev/null @@ -1,43 +0,0 @@ -# `extern_absolute_paths` - -The tracking issue for this feature is: [#44660] - -[#44660]: https://github.com/rust-lang/rust/issues/44660 - ------------------------- - -The `extern_absolute_paths` feature enables mode allowing to refer to names from other crates -"inline", without introducing `extern crate` items, using absolute paths like `::my_crate::a::b`. - -`::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`. - -`feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring -to absolute paths in the local crate (`crate::a::b`). - -`feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to -paths from other crates (`extern::my_crate::a::b`). - -```rust,ignore -#![feature(extern_absolute_paths)] - -// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern` -// options, or standard Rust distribution, or some other means. - -use xcrate::Z; - -fn f() { - use xcrate; - use xcrate as ycrate; - let s = xcrate::S; - assert_eq!(format!("{:?}", s), "S"); - let z = ycrate::Z; - assert_eq!(format!("{:?}", z), "Z"); -} - -fn main() { - let s = ::xcrate::S; - assert_eq!(format!("{:?}", s), "S"); - let z = Z; - assert_eq!(format!("{:?}", z), "Z"); -} -``` diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 29ba433bec7..11b91591593 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -65,13 +65,12 @@ use core::iter::FusedIterator; use core::marker::{Unpin, Unsize}; use core::mem; -use core::pin::PinMut; +use core::pin::Pin; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError}; use raw_vec::RawVec; -use pin::PinBox; use str::from_boxed_utf8_unchecked; /// A pointer type for heap allocation. @@ -97,6 +96,12 @@ impl Box { pub fn new(x: T) -> Box { box x } + + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn pinned(x: T) -> Pin> { + (box x).into() + } } impl Box { @@ -427,6 +432,16 @@ fn from(t: T) -> Self { } } +#[unstable(feature = "pin", issue = "49150")] +impl From> for Pin> { + fn from(boxed: Box) -> Self { + // It's not possible to move or replace the insides of a `Pin>` + // when `T: !Unpin`, so it's safe to pin it directly without any + // additional requirements. + unsafe { Pin::new_unchecked(boxed) } + } +} + #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { fn from(slice: &'a [T]) -> Box<[T]> { @@ -789,8 +804,8 @@ unsafe fn resume(&mut self) -> GeneratorState { impl Future for Box { type Output = F::Output; - fn poll(mut self: PinMut, cx: &mut Context) -> Poll { - PinMut::new(&mut **self).poll(cx) + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + F::poll(Pin::new(&mut *self), cx) } } @@ -804,8 +819,8 @@ fn into_raw(self) -> *mut () { unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { let ptr = ptr as *mut F; - let pin: PinMut = PinMut::new_unchecked(&mut *ptr); - pin.poll(cx) + let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr); + F::poll(pin, cx) } unsafe fn drop(ptr: *mut ()) { @@ -843,9 +858,16 @@ fn from(boxed: Box) -> Self { } } -#[unstable(feature = "pin", issue = "49150")] -impl From> for Box { - fn from(pinned: PinBox) -> Box { - unsafe { PinBox::unpin(pinned) } +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + Send + 'a> From>> for FutureObj<'a, ()> { + fn from(boxed: Pin>) -> Self { + FutureObj::new(boxed) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + 'a> From>> for LocalFutureObj<'a, ()> { + fn from(boxed: Pin>) -> Self { + LocalFutureObj::new(boxed) } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2d271fd0dca..b2303a02cb2 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -160,7 +160,6 @@ mod boxed { pub mod sync; pub mod rc; pub mod raw_vec; -pub mod pin; pub mod prelude; pub mod borrow; pub mod fmt; diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs deleted file mode 100644 index 17bbc9882d9..00000000000 --- a/src/liballoc/pin.rs +++ /dev/null @@ -1,302 +0,0 @@ -//! Types which pin data to its location in memory -//! -//! It is sometimes useful to have objects that are guaranteed to not move, -//! in the sense that their placement in memory does not change, and can thus be relied upon. -//! -//! A prime example of such a scenario would be building self-referencial structs, -//! since moving an object with pointers to itself will invalidate them, -//! which could cause undefined behavior. -//! -//! In order to prevent objects from moving, they must be *pinned*, -//! by wrapping the data in pinning pointer types, such as [`PinMut`] and [`PinBox`], -//! which are otherwise equivalent to `& mut` and [`Box`], respectively. -//! -//! First of all, these are pointer types because pinned data mustn't be passed around by value -//! (that would change its location in memory). -//! Secondly, since data can be moved out of `&mut` and [`Box`] with functions such as [`swap`], -//! which causes their contents to swap places in memory, -//! we need dedicated types that prohibit such operations. -//! -//! However, these restrictions are usually not necessary, -//! so most types implement the [`Unpin`] auto-trait, -//! which indicates that the type can be moved out safely. -//! Doing so removes the limitations of pinning types, -//! making them the same as their non-pinning counterparts. -//! -//! [`PinMut`]: struct.PinMut.html -//! [`PinBox`]: struct.PinBox.html -//! [`Unpin`]: trait.Unpin.html -//! [`swap`]: ../../std/mem/fn.swap.html -//! [`Box`]: ../boxed/struct.Box.html -//! -//! # Examples -//! -//! ```rust -//! #![feature(pin)] -//! -//! use std::pin::PinBox; -//! use std::marker::Pinned; -//! use std::ptr::NonNull; -//! -//! // This is a self referencial struct since the slice field points to the data field. -//! // We cannot inform the compiler about that with a normal reference, -//! // since this pattern cannot be described with the usual borrowing rules. -//! // Instead we use a raw pointer, though one which is known to not be null, -//! // since we know it's pointing at the string. -//! struct Unmovable { -//! data: String, -//! slice: NonNull, -//! _pin: Pinned, -//! } -//! -//! impl Unmovable { -//! // To ensure the data doesn't move when the function returns, -//! // we place it in the heap where it will stay for the lifetime of the object, -//! // and the only way to access it would be through a pointer to it. -//! fn new(data: String) -> PinBox { -//! let res = Unmovable { -//! data, -//! // we only create the pointer once the data is in place -//! // otherwise it will have already moved before we even started -//! slice: NonNull::dangling(), -//! _pin: Pinned, -//! }; -//! let mut boxed = PinBox::new(res); -//! -//! let slice = NonNull::from(&boxed.data); -//! // we know this is safe because modifying a field doesn't move the whole struct -//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; -//! boxed -//! } -//! } -//! -//! let unmoved = Unmovable::new("hello".to_string()); -//! // The pointer should point to the correct location, -//! // so long as the struct hasn't moved. -//! // Meanwhile, we are free to move the pointer around. -//! # #[allow(unused_mut)] -//! let mut still_unmoved = unmoved; -//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); -//! -//! // Since our type doesn't implement Unpin, this will fail to compile: -//! // let new_unmoved = Unmovable::new("world".to_string()); -//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); -//! ``` - -#![unstable(feature = "pin", issue = "49150")] - -pub use core::pin::*; -pub use core::marker::Unpin; - -use core::convert::From; -use core::fmt; -use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; -use core::marker::Unsize; -use core::ops::{CoerceUnsized, Deref, DerefMut}; -use core::task::{Context, Poll}; - -use boxed::Box; - -/// A pinned, heap allocated reference. -/// -/// This type is similar to [`Box`], except that it pins its value, -/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. -/// -/// See the [module documentation] for furthur explaination on pinning. -/// -/// [`Box`]: ../boxed/struct.Box.html -/// [`Unpin`]: ../../std/marker/trait.Unpin.html -/// [module documentation]: index.html -#[unstable(feature = "pin", issue = "49150")] -#[fundamental] -#[repr(transparent)] -pub struct PinBox { - inner: Box, -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Allocate memory on the heap, move the data into it and pin it. - #[unstable(feature = "pin", issue = "49150")] - pub fn new(data: T) -> PinBox { - PinBox { inner: Box::new(data) } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Get a pinned reference to the data in this PinBox. - #[inline] - pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { - unsafe { PinMut::new_unchecked(&mut *self.inner) } - } - - /// Constructs a `PinBox` from a raw pointer. - /// - /// After calling this function, the raw pointer is owned by the - /// resulting `PinBox`. Specifically, the `PinBox` destructor will call - /// the destructor of `T` and free the allocated memory. Since the - /// way `PinBox` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `PinBox` via the [`PinBox::into_raw`] function. - /// - /// This function is unsafe because improper use may lead to - /// memory problems. For example, a double-free may occur if the - /// function is called twice on the same raw pointer. - /// - /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::pin::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// let x = unsafe { PinBox::from_raw(ptr) }; - /// ``` - #[inline] - pub unsafe fn from_raw(raw: *mut T) -> Self { - PinBox { inner: Box::from_raw(raw) } - } - - /// Consumes the `PinBox`, returning the wrapped raw pointer. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `PinBox`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `PinBox` with the [`PinBox::from_raw`] function. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::pin::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// ``` - #[inline] - pub fn into_raw(b: PinBox) -> *mut T { - Box::into_raw(b.inner) - } - - /// Get a mutable reference to the data inside this PinBox. - /// - /// This function is unsafe. Users must guarantee that the data is never - /// moved out of this reference. - #[inline] - pub unsafe fn get_mut<'a>(this: &'a mut PinBox) -> &'a mut T { - &mut *this.inner - } - - /// Convert this PinBox into an unpinned Box. - /// - /// This function is unsafe. Users must guarantee that the data is never - /// moved out of the box. - #[inline] - pub unsafe fn unpin(this: PinBox) -> Box { - this.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl From> for PinBox { - fn from(boxed: Box) -> PinBox { - PinBox { inner: boxed } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl Deref for PinBox { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl DerefMut for PinBox { - fn deref_mut(&mut self) -> &mut T { - &mut *self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Display for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Debug for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Pointer for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // It's not possible to extract the inner Uniq directly from the Box, - // instead we cast it to a *const which aliases the Unique - let ptr: *const T = &*self.inner; - fmt::Pointer::fmt(&ptr, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl, U: ?Sized> CoerceUnsized> for PinBox {} - -#[unstable(feature = "pin", issue = "49150")] -impl Unpin for PinBox {} - -#[unstable(feature = "futures_api", issue = "50547")] -impl Future for PinBox { - type Output = F::Output; - - fn poll(mut self: PinMut, cx: &mut Context) -> Poll { - self.as_pin_mut().poll(cx) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox - where F: Future + 'a -{ - fn into_raw(self) -> *mut () { - PinBox::into_raw(self) as *mut () - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - let ptr = ptr as *mut F; - let pin: PinMut = PinMut::new_unchecked(&mut *ptr); - pin.poll(cx) - } - - unsafe fn drop(ptr: *mut ()) { - drop(PinBox::from_raw(ptr as *mut F)) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { - FutureObj::new(boxed) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { - LocalFutureObj::new(boxed) - } -} diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index fcd683e5e87..9d951691a34 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -256,6 +256,7 @@ use core::mem::{self, align_of_val, forget, size_of_val}; use core::ops::Deref; use core::ops::CoerceUnsized; +use core::pin::Pin; use core::ptr::{self, NonNull}; use core::convert::From; use core::usize; @@ -321,6 +322,11 @@ pub fn new(value: T) -> Rc { } } + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(value: T) -> Pin> { + unsafe { Pin::new_unchecked(Rc::new(value)) } + } + /// Returns the contained value, if the `Rc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 9d442b3e00c..6c0b1c33a1f 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -392,6 +392,10 @@ pub fn into_vec(self: Box) -> Vec { /// Creates a vector by repeating a slice `n` times. /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// /// # Examples /// /// Basic usage: @@ -403,6 +407,16 @@ pub fn into_vec(self: Box) -> Vec { /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); /// } /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// #![feature(repeat_generic_slice)] + /// fn main() { + /// // this will panic at runtime + /// b"0123456789abcdef".repeat(usize::max_value()); + /// } + /// ``` #[unstable(feature = "repeat_generic_slice", reason = "it's on str, why not on slice?", issue = "48784")] @@ -417,7 +431,7 @@ pub fn repeat(&self, n: usize) -> Vec where T: Copy { // and `rem` is the remaining part of `n`. // Using `Vec` to access `set_len()`. - let mut buf = Vec::with_capacity(self.len() * n); + let mut buf = Vec::with_capacity(self.len().checked_mul(n).expect("capacity overflow")); // `2^expn` repetition is done by doubling `buf` `expn`-times. buf.extend(self); diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index c451a051c74..2af89562d69 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -515,6 +515,10 @@ pub fn into_string(self: Box) -> String { /// Creates a new [`String`] by repeating a string `n` times. /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// /// [`String`]: string/struct.String.html /// /// # Examples @@ -524,6 +528,15 @@ pub fn into_string(self: Box) -> String { /// ``` /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// fn main() { + /// // this will panic at runtime + /// "0123456789abcdef".repeat(usize::max_value()); + /// } + /// ``` #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 8b4231dbdf6..116393bdad1 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -26,6 +26,7 @@ use core::mem::{self, align_of_val, size_of_val}; use core::ops::Deref; use core::ops::CoerceUnsized; +use core::pin::Pin; use core::ptr::{self, NonNull}; use core::marker::{Unpin, Unsize, PhantomData}; use core::hash::{Hash, Hasher}; @@ -297,6 +298,11 @@ pub fn new(data: T) -> Arc { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(data: T) -> Pin> { + unsafe { Pin::new_unchecked(Arc::new(data)) } + } + /// Returns the contained value, if the `Arc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e9c1a3df518..7fc4453fec5 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2410,9 +2410,8 @@ fn next(&mut self) -> Option { // same pointer. self.ptr = arith_offset(self.ptr as *const i8, 1) as *mut T; - // Use a non-null pointer value - // (self.ptr might be null because of wrapping) - Some(ptr::read(1 as *mut T)) + // Make up a value of this ZST. + Some(mem::zeroed()) } else { let old = self.ptr; self.ptr = self.ptr.offset(1); @@ -2451,9 +2450,8 @@ fn next_back(&mut self) -> Option { // See above for why 'ptr.offset' isn't used self.end = arith_offset(self.end as *const i8, -1) as *mut T; - // Use a non-null pointer value - // (self.end might be null because of wrapping) - Some(ptr::read(1 as *mut T)) + // Make up a value of this ZST. + Some(mem::zeroed()) } else { self.end = self.end.offset(-1); diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs new file mode 100644 index 00000000000..a03756f9c22 --- /dev/null +++ b/src/libcore/ffi.rs @@ -0,0 +1,42 @@ +#![stable(feature = "", since = "1.30.0")] + +#![allow(non_camel_case_types)] + +//! Utilities related to FFI bindings. + +use ::fmt; + +/// Equivalent to C's `void` type when used as a [pointer]. +/// +/// In essence, `*const c_void` is equivalent to C's `const void*` +/// and `*mut c_void` is equivalent to C's `void*`. That said, this is +/// *not* the same as C's `void` return type, which is Rust's `()` type. +/// +/// Ideally, this type would be equivalent to [`!`], but currently it may +/// be more ideal to use `c_void` for FFI purposes. +/// +/// [`!`]: ../../std/primitive.never.html +/// [pointer]: ../../std/primitive.pointer.html +// NB: For LLVM to recognize the void pointer type and by extension +// functions like malloc(), we need to have it represented as i8* in +// LLVM bitcode. The enum used here ensures this and prevents misuse +// of the "raw" type by only having private variants.. We need two +// variants, because the compiler complains about the repr attribute +// otherwise. +#[repr(u8)] +#[stable(feature = "raw_os", since = "1.1.0")] +pub enum c_void { + #[unstable(feature = "c_void_variant", reason = "should not have to exist", + issue = "0")] + #[doc(hidden)] __variant1, + #[unstable(feature = "c_void_variant", reason = "should not have to exist", + issue = "0")] + #[doc(hidden)] __variant2, +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("c_void") + } +} diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 520b6ebbbaa..f4b5cf95e37 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -12,8 +12,9 @@ reason = "futures in libcore are unstable", issue = "50547")] -use pin::PinMut; use marker::Unpin; +use ops; +use pin::Pin; use task::{self, Poll}; /// A future represents an asychronous computation. @@ -92,21 +93,25 @@ pub trait Future { /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready /// [`cx.waker()`]: ../task/struct.Context.html#method.waker - fn poll(self: PinMut, cx: &mut task::Context) -> Poll; + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll; } impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F { type Output = F::Output; - fn poll(mut self: PinMut, cx: &mut task::Context) -> Poll { - F::poll(PinMut::new(&mut **self), cx) + fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + F::poll(Pin::new(&mut **self), cx) } } -impl<'a, F: ?Sized + Future> Future for PinMut<'a, F> { - type Output = F::Output; +impl

Future for Pin

+where + P: ops::DerefMut, + P::Target: Future, +{ + type Output = <

::Target as Future>::Output; - fn poll(mut self: PinMut, cx: &mut task::Context) -> Poll { - F::poll((*self).reborrow(), cx) + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + Pin::get_mut(self).as_mut().poll(cx) } } diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 68fe461aeae..b335cac6c1d 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -15,7 +15,8 @@ use fmt; use future::Future; use marker::{PhantomData, Unpin}; -use pin::PinMut; +use ops; +use pin::Pin; use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to @@ -78,9 +79,9 @@ impl<'a, T> Future for LocalFutureObj<'a, T> { type Output = T; #[inline] - fn poll(self: PinMut, cx: &mut Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { unsafe { - (self.poll_fn)(self.ptr, cx) + ((*self).poll_fn)((*self).ptr, cx) } } } @@ -128,9 +129,11 @@ impl<'a, T> Future for FutureObj<'a, T> { type Output = T; #[inline] - fn poll(self: PinMut, cx: &mut Context) -> Poll { - let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) }; - pinned_field.poll(cx) + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let pinned_field: Pin<&mut LocalFutureObj<'a, T>> = unsafe { + Pin::map_unchecked_mut(self, |x| &mut x.0) + }; + LocalFutureObj::poll(pinned_field, cx) } } @@ -175,7 +178,25 @@ fn into_raw(self) -> *mut () { } unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) + let p: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F)); + F::poll(p, cx) + } + + unsafe fn drop(_ptr: *mut ()) {} +} + +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, P, F> UnsafeFutureObj<'a, T> for Pin

where + P: ops::DerefMut + 'a, + F: Future + 'a, +{ + fn into_raw(mut self) -> *mut () { + unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) as *mut F as *mut () } + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + let future: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F)); + F::poll(future, cx) } unsafe fn drop(_ptr: *mut ()) {} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 763409327de..675e73e952c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -202,6 +202,7 @@ pub mod option; pub mod raw; pub mod result; +pub mod ffi; pub mod slice; pub mod str; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index dd57d2dd009..5572fe1512c 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -609,7 +609,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// this trait cannot prevent types from moving by itself. /// /// Instead it can be used to prevent moves through the type system, -/// by controlling the behavior of special pointer types like [`PinMut`], +/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper, /// which "pin" the type in place by not allowing it to be moved out of them. /// See the [`pin module`] documentation for more information on pinning. /// @@ -621,10 +621,10 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// ```rust /// #![feature(pin)] /// use std::mem::replace; -/// use std::pin::PinMut; +/// use std::pin::Pin; /// /// let mut string = "this".to_string(); -/// let mut pinned_string = PinMut::new(&mut string); +/// let mut pinned_string = Pin::new(&mut string); /// /// // dereferencing the pointer mutably is only possible because String implements Unpin /// replace(&mut *pinned_string, "other".to_string()); @@ -633,7 +633,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// This trait is automatically implemented for almost every type. /// /// [`replace`]: ../../std/mem/fn.replace.html -/// [`PinMut`]: ../pin/struct.PinMut.html +/// [`Pin`]: ../pin/struct.Pin.html /// [`pin module`]: ../../std/pin/index.html #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index dfdc375765d..58bf6be834d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -147,7 +147,7 @@ use iter::{FromIterator, FusedIterator, TrustedLen}; use {hint, mem, ops::{self, Deref}}; -use pin::PinMut; +use pin::Pin; // Note that this is not a lang item per se, but it has a hidden dependency on // `Iterator`, which is one. The compiler assumes that the `next` method of @@ -270,12 +270,22 @@ pub fn as_mut(&mut self) -> Option<&mut T> { } } - /// Converts from `Option` to `Option>` + + /// Converts from `Pin<&Option>` to `Option>` + #[inline] + #[unstable(feature = "pin", issue = "49150")] + pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { + unsafe { + Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) + } + } + + /// Converts from `Pin<&mut Option>` to `Option>` #[inline] #[unstable(feature = "pin", issue = "49150")] - pub fn as_pin_mut<'a>(self: PinMut<'a, Self>) -> Option> { + pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { unsafe { - PinMut::get_mut_unchecked(self).as_mut().map(|x| PinMut::new_unchecked(x)) + Pin::get_mut_unchecked(self).as_mut().map(|x| Pin::new_unchecked(x)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index e9001f86b35..d09a545aecf 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -1,160 +1,328 @@ //! Types which pin data to its location in memory //! -//! See the [standard library module] for more information. +//! It is sometimes useful to have objects that are guaranteed to not move, +//! in the sense that their placement in memory does not change, and can thus be relied upon. //! -//! [standard library module]: ../../std/pin/index.html +//! A prime example of such a scenario would be building self-referencial structs, +//! since moving an object with pointers to itself will invalidate them, +//! which could cause undefined behavior. +//! +//! In order to prevent objects from moving, they must be pinned +//! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped +//! in a `Pin` is otherwise equivalent to its normal version, e.g. `Pin>` +//! and `Box` work the same way except that the first is pinning the value +//! of `T` in place. +//! +//! First of all, these are pointer types because pinned data mustn't be passed around by value +//! (that would change its location in memory). +//! Secondly, since data can be moved out of `&mut` and `Box` with functions such as [`swap`], +//! which causes their contents to swap places in memory, +//! we need dedicated types that prohibit such operations. +//! +//! However, these restrictions are usually not necessary, +//! so most types implement the [`Unpin`] auto-trait, +//! which indicates that the type can be moved out safely. +//! Doing so removes the limitations of pinning types, +//! making them the same as their non-pinning counterparts. +//! +//! [`Pin`]: struct.Pin.html +//! [`Unpin`]: trait.Unpin.html +//! [`swap`]: ../../std/mem/fn.swap.html +//! [`Box`]: ../../std/boxed/struct.Box.html +//! +//! # Examples +//! +//! ```rust +//! #![feature(pin)] +//! +//! use std::pin::Pin; +//! use std::marker::Pinned; +//! use std::ptr::NonNull; +//! +//! // This is a self referencial struct since the slice field points to the data field. +//! // We cannot inform the compiler about that with a normal reference, +//! // since this pattern cannot be described with the usual borrowing rules. +//! // Instead we use a raw pointer, though one which is known to not be null, +//! // since we know it's pointing at the string. +//! struct Unmovable { +//! data: String, +//! slice: NonNull, +//! _pin: Pinned, +//! } +//! +//! impl Unmovable { +//! // To ensure the data doesn't move when the function returns, +//! // we place it in the heap where it will stay for the lifetime of the object, +//! // and the only way to access it would be through a pointer to it. +//! fn new(data: String) -> Pin> { +//! let res = Unmovable { +//! data, +//! // we only create the pointer once the data is in place +//! // otherwise it will have already moved before we even started +//! slice: NonNull::dangling(), +//! _pin: Pinned, +//! }; +//! let mut boxed = Box::pinned(res); +//! +//! let slice = NonNull::from(&boxed.data); +//! // we know this is safe because modifying a field doesn't move the whole struct +//! unsafe { +//! let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); +//! Pin::get_mut_unchecked(mut_ref).slice = slice; +//! } +//! boxed +//! } +//! } +//! +//! let unmoved = Unmovable::new("hello".to_string()); +//! // The pointer should point to the correct location, +//! // so long as the struct hasn't moved. +//! // Meanwhile, we are free to move the pointer around. +//! # #[allow(unused_mut)] +//! let mut still_unmoved = unmoved; +//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); +//! +//! // Since our type doesn't implement Unpin, this will fail to compile: +//! // let new_unmoved = Unmovable::new("world".to_string()); +//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); +//! ``` #![unstable(feature = "pin", issue = "49150")] use fmt; -use future::{Future, UnsafeFutureObj}; -use marker::{Sized, Unpin, Unsize}; -use task::{Context, Poll}; +use marker::Sized; use ops::{Deref, DerefMut, CoerceUnsized}; -/// A pinned reference. +#[doc(inline)] +pub use marker::Unpin; + +/// A pinned pointer. /// -/// This type is similar to a mutable reference, except that it pins its value, -/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. +/// This is a wrapper around a kind of pointer which makes that pointer "pin" its +/// value in place, preventing the value referenced by that pointer from being moved +/// unless it implements [`Unpin`]. /// /// See the [`pin` module] documentation for furthur explanation on pinning. /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html +// +// Note: the derives below are allowed because they all only use `&P`, so they +// cannot move the value behind `pointer`. #[unstable(feature = "pin", issue = "49150")] #[fundamental] -pub struct PinMut<'a, T: ?Sized + 'a> { - inner: &'a mut T, +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +pub struct Pin

{ + pointer: P, } -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> PinMut<'a, T> { - /// Construct a new `PinMut` around a reference to some data of a type that +impl Pin

+where + P::Target: Unpin, +{ + /// Construct a new `Pin` around a pointer to some data of a type that /// implements `Unpin`. #[unstable(feature = "pin", issue = "49150")] - pub fn new(reference: &'a mut T) -> PinMut<'a, T> { - PinMut { inner: reference } + #[inline(always)] + pub fn new(pointer: P) -> Pin

{ + // Safety: the value pointed to is `Unpin`, and so has no requirements + // around pinning. + unsafe { Pin::new_unchecked(pointer) } } +} - /// Get a mutable reference to the data inside of this `PinMut`. +impl Pin

{ + /// Construct a new `Pin` around a reference to some data of a type that + /// may or may not implement `Unpin`. + /// + /// # Safety + /// + /// This constructor is unsafe because we cannot guarantee that the data + /// pointed to by `pointer` is pinned. If the constructed `Pin

` does + /// not guarantee that the data `P` points to is pinned, constructing a + /// `Pin

` is undefined behavior. + /// + /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used + /// instead. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub unsafe fn new_unchecked(pointer: P) -> Pin

{ + Pin { pointer } + } + + /// Get a pinned shared reference from this pinned pointer. #[unstable(feature = "pin", issue = "49150")] - pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T { - this.inner + #[inline(always)] + pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { + unsafe { Pin::new_unchecked(&*self.pointer) } } } +impl Pin

{ + /// Get a pinned mutable reference from this pinned pointer. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { + unsafe { Pin::new_unchecked(&mut *self.pointer) } + } -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> PinMut<'a, T> { - /// Construct a new `PinMut` around a reference to some data of a type that - /// may or may not implement `Unpin`. + /// Assign a new value to the memory behind the pinned reference. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn set(mut self: Pin

, value: P::Target) + where + P::Target: Sized, + { + *self.pointer = value; + } +} + +impl<'a, T: ?Sized> Pin<&'a T> { + /// Construct a new pin by mapping the interior value. /// - /// This constructor is unsafe because we do not know what will happen with - /// that data after the lifetime of the reference ends. If you cannot guarantee that the - /// data will never move again, calling this constructor is invalid. + /// For example, if you wanted to get a `Pin` of a field of something, + /// you could use this to get access to that field in one line of code. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that the data you return + /// will not move so long as the argument value does not move (for example, + /// because it is one of the fields of that value), and also that you do + /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> { - PinMut { inner: reference } + pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where + F: FnOnce(&T) -> &U, + { + let pointer = &*this.pointer; + let new_pointer = func(pointer); + Pin::new_unchecked(new_pointer) } - /// Reborrow a `PinMut` for a shorter lifetime. + /// Get a shared reference out of a pin. /// - /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a - /// short-lived mutable reference reborrowing from `x`. + /// Note: `Pin` also implements `Deref` to the target, which can be used + /// to access the inner value. However, `Deref` only provides a reference + /// that lives for as long as the borrow of the `Pin`, not the lifetime of + /// the `Pin` itself. This method allows turning the `Pin` into a reference + /// with the same lifetime as the original `Pin`. #[unstable(feature = "pin", issue = "49150")] - pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> { - PinMut { inner: self.inner } + #[inline(always)] + pub fn get_ref(this: Pin<&'a T>) -> &'a T { + this.pointer + } +} + +impl<'a, T: ?Sized> Pin<&'a mut T> { + /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> { + Pin { pointer: this.pointer } + } + + /// Get a mutable reference to the data inside of this `Pin`. + /// + /// This requires that the data inside this `Pin` is `Unpin`. + /// + /// Note: `Pin` also implements `DerefMut` to the data, which can be used + /// to access the inner value. However, `DerefMut` only provides a reference + /// that lives for as long as the borrow of the `Pin`, not the lifetime of + /// the `Pin` itself. This method allows turning the `Pin` into a reference + /// with the same lifetime as the original `Pin`. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T + where T: Unpin, + { + this.pointer } - /// Get a mutable reference to the data inside of this `PinMut`. + /// Get a mutable reference to the data inside of this `Pin`. + /// + /// # Safety /// /// This function is unsafe. You must guarantee that you will never move /// the data out of the mutable reference you receive when you call this - /// function. + /// function, so that the invariants on the `Pin` type can be upheld. + /// + /// If the underlying data is `Unpin`, `Pin::get_mut` should be used + /// instead. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T { - this.inner + #[inline(always)] + pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T { + this.pointer } /// Construct a new pin by mapping the interior value. /// - /// For example, if you wanted to get a `PinMut` of a field of something, + /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. /// + /// # Safety + /// /// This function is unsafe. You must guarantee that the data you return /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where - F: FnOnce(&mut T) -> &mut U + pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where + F: FnOnce(&mut T) -> &mut U, { - PinMut { inner: f(this.inner) } - } - - /// Assign a new value to the memory behind the pinned reference. - #[unstable(feature = "pin", issue = "49150")] - pub fn set(this: PinMut<'a, T>, value: T) - where T: Sized, - { - *this.inner = value; + let pointer = Pin::get_mut_unchecked(this); + let new_pointer = func(pointer); + Pin::new_unchecked(new_pointer) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Deref for PinMut<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner +impl Deref for Pin

{ + type Target = P::Target; + fn deref(&self) -> &P::Target { + Pin::get_ref(Pin::as_ref(self)) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> { - fn deref_mut(&mut self) -> &mut T { - self.inner +impl DerefMut for Pin

+where + P::Target: Unpin +{ + fn deref_mut(&mut self) -> &mut P::Target { + Pin::get_mut(Pin::as_mut(self)) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> { +impl<'a, P: fmt::Debug> fmt::Debug for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) + fmt::Debug::fmt(&self.pointer, f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> { +impl<'a, P: fmt::Display> fmt::Display for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) + fmt::Display::fmt(&self.pointer, f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> { +impl<'a, P: fmt::Pointer> fmt::Pointer for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&(&*self.inner as *const T), f) + fmt::Pointer::fmt(&self.pointer, f) } } +// Note: this means that any impl of `CoerceUnsized` that allows coercing from +// a type that impls `Deref` to a type that impls +// `Deref` is unsound. Any such impl would probably be unsound +// for other reasons, though, so we just need to take care not to allow such +// impls to land in std. #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinMut<'a, T> {} +impl<'a, P, U> CoerceUnsized> for Pin

+where + P: CoerceUnsized, +{} #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} - -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F> - where F: Future + 'a -{ - fn into_raw(self) -> *mut () { - unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () } - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) - } - - unsafe fn drop(_ptr: *mut ()) {} -} +impl<'a, P> Unpin for Pin

{} diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 62adaea168a..da4a56cfecd 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1739,8 +1739,9 @@ fn gcd(a: usize, b: usize) -> usize { /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. The middle slice will have the greatest length - /// possible for a given type and input slice. + /// slice of a new type, and the suffix slice. The method does a best effort to make the + /// middle slice the greatest length possible for a given type and input slice, but only + /// your algorithm's performance should depend on that, not its correctness. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -1755,7 +1756,6 @@ fn gcd(a: usize, b: usize) -> usize { /// Basic usage: /// /// ``` - /// # #![feature(slice_align_to)] /// unsafe { /// let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7]; /// let (prefix, shorts, suffix) = bytes.align_to::(); @@ -1764,7 +1764,7 @@ fn gcd(a: usize, b: usize) -> usize { /// // less_efficient_algorithm_for_bytes(suffix); /// } /// ``` - #[unstable(feature = "slice_align_to", issue = "44488")] + #[stable(feature = "slice_align_to", since = "1.30.0")] pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { // Note that most of this function will be constant-evaluated, if ::mem::size_of::() == 0 || ::mem::size_of::() == 0 { @@ -1792,8 +1792,9 @@ pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. The middle slice will have the greatest length - /// possible for a given type and input slice. + /// slice of a new type, and the suffix slice. The method does a best effort to make the + /// middle slice the greatest length possible for a given type and input slice, but only + /// your algorithm's performance should depend on that, not its correctness. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -1808,7 +1809,6 @@ pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { /// Basic usage: /// /// ``` - /// # #![feature(slice_align_to)] /// unsafe { /// let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7]; /// let (prefix, shorts, suffix) = bytes.align_to_mut::(); @@ -1817,7 +1817,7 @@ pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { /// // less_efficient_algorithm_for_bytes(suffix); /// } /// ``` - #[unstable(feature = "slice_align_to", issue = "44488")] + #[stable(feature = "slice_align_to", since = "1.30.0")] pub unsafe fn align_to_mut(&mut self) -> (&mut [T], &mut [U], &mut [T]) { // Note that most of this function will be constant-evaluated, if ::mem::size_of::() == 0 || ::mem::size_of::() == 0 { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index e48f3b36c65..4f3086575c0 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,7 +34,6 @@ #![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] -#![feature(slice_align_to)] #![feature(align_offset)] #![feature(reverse_bits)] #![feature(inner_deref)] diff --git a/src/libcore/time.rs b/src/libcore/time.rs index b58920224eb..1aed5a7b426 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -21,7 +21,7 @@ //! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); //! ``` -use fmt; +use {fmt, u64}; use iter::Sum; use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; @@ -30,6 +30,7 @@ const NANOS_PER_MICRO: u32 = 1_000; const MILLIS_PER_SEC: u64 = 1_000; const MICROS_PER_SEC: u64 = 1_000_000; +const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64; /// A `Duration` type to represent a span of time, typically used for system /// timeouts. @@ -458,6 +459,115 @@ pub fn checked_div(self, rhs: u32) -> Option { None } } + + /// Returns the number of seconds contained by this `Duration` as `f64`. + /// + /// The returned value does include the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.as_float_secs(), 2.7); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn as_float_secs(&self) -> f64 { + (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64) + } + + /// Creates a new `Duration` from the specified number of seconds. + /// + /// # Panics + /// This constructor will panic if `secs` is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::from_float_secs(2.7); + /// assert_eq!(dur, Duration::new(2, 700_000_000)); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn from_float_secs(secs: f64) -> Duration { + let nanos = secs * (NANOS_PER_SEC as f64); + if !nanos.is_finite() { + panic!("got non-finite value when converting float to duration"); + } + if nanos >= MAX_NANOS_F64 { + panic!("overflow when converting float to duration"); + } + if nanos < 0.0 { + panic!("underflow when converting float to duration"); + } + let nanos = nanos as u128; + Duration { + secs: (nanos / (NANOS_PER_SEC as u128)) as u64, + nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, + } + } + + /// Multiply `Duration` by `f64`. + /// + /// # Panics + /// This method will panic if result is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000)); + /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0)); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn mul_f64(self, rhs: f64) -> Duration { + Duration::from_float_secs(rhs * self.as_float_secs()) + } + + /// Divide `Duration` by `f64`. + /// + /// # Panics + /// This method will panic if result is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611)); + /// // note that truncation is used, not rounding + /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598)); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn div_f64(self, rhs: f64) -> Duration { + Duration::from_float_secs(self.as_float_secs() / rhs) + } + + /// Divide `Duration` by `Duration` and return `f64`. + /// + /// # Examples + /// ``` + /// #![feature(duration_float)] + /// use std::time::Duration; + /// + /// let dur1 = Duration::new(2, 700_000_000); + /// let dur2 = Duration::new(5, 400_000_000); + /// assert_eq!(dur1.div_duration(dur2), 0.5); + /// ``` + #[unstable(feature = "duration_float", issue = "54361")] + #[inline] + pub fn div_duration(self, rhs: Duration) -> f64 { + self.as_float_secs() / rhs.as_float_secs() + } } #[stable(feature = "duration", since = "1.3.0")] @@ -501,6 +611,15 @@ fn mul(self, rhs: u32) -> Duration { } } +#[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")] +impl Mul for u32 { + type Output = Duration; + + fn mul(self, rhs: Duration) -> Duration { + rhs * self + } +} + #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl MulAssign for Duration { fn mul_assign(&mut self, rhs: u32) { diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 1b974809203..6b9c0aac52e 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -556,7 +556,10 @@ fn add_exiting_edge(&mut self, target_scope: region::Scope, to_index: CFGIndex) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; - let mut scope = region::Scope::Node(from_expr.hir_id.local_id); + let mut scope = region::Scope { + id: from_expr.hir_id.local_id, + data: region::ScopeData::Node + }; let region_scope_tree = self.tcx.region_scope_tree(self.owner_def_id); while scope != target_scope { data.exiting_scopes.push(scope.item_local_id()); @@ -586,8 +589,11 @@ fn find_scope_edge(&self, Ok(loop_id) => { for b in &self.breakable_block_scopes { if b.block_expr_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { - let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; - return (region::Scope::Node(scope_id), match scope_cf_kind { + let scope = region::Scope { + id: self.tcx.hir.node_to_hir_id(loop_id).local_id, + data: region::ScopeData::Node + }; + return (scope, match scope_cf_kind { ScopeCfKind::Break => b.break_index, ScopeCfKind::Continue => bug!("can't continue to block"), }); @@ -595,8 +601,11 @@ fn find_scope_edge(&self, } for l in &self.loop_scopes { if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { - let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; - return (region::Scope::Node(scope_id), match scope_cf_kind { + let scope = region::Scope { + id: self.tcx.hir.node_to_hir_id(loop_id).local_id, + data: region::ScopeData::Node + }; + return (scope, match scope_cf_kind { ScopeCfKind::Break => l.break_index, ScopeCfKind::Continue => l.continue_index, }); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 31fba3ad974..6e35755d9a4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -709,17 +709,22 @@ pub fn get_parent(&self, id: NodeId) -> NodeId { } } - /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no + /// Returns the DefId of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. pub fn get_module_parent(&self, id: NodeId) -> DefId { - let id = match self.walk_parent_nodes(id, |node| match *node { + self.local_def_id(self.get_module_parent_node(id)) + } + + /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no + /// module parent is in this map. + pub fn get_module_parent_node(&self, id: NodeId) -> NodeId { + match self.walk_parent_nodes(id, |node| match *node { Node::Item(&Item { node: ItemKind::Mod(_), .. }) => true, _ => false, }, |_| false) { Ok(id) => id, Err(id) => id, - }; - self.local_def_id(id) + } } /// Returns the nearest enclosing scope. A scope is an item or block. diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a0c96554c91..cf76c3b7e02 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -118,7 +118,7 @@ pub fn note_and_explain_region( return; } }; - let scope_decorated_tag = match scope.data() { + let scope_decorated_tag = match scope.data { region::ScopeData::Node => tag, region::ScopeData::CallSite => "scope of call-site for function", region::ScopeData::Arguments => "scope of function body", diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 168285b455f..97b1978cb2e 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -56,9 +56,9 @@ pub(super) fn try_report_anon_anon_conflict(&self) -> Option { let (span, sub, sup) = self.get_regions(); // Determine whether the sub and sup consist of both anonymous (elided) regions. - let anon_reg_sup = self.is_suitable_region(sup)?; + let anon_reg_sup = self.tcx.is_suitable_region(sup)?; - let anon_reg_sub = self.is_suitable_region(sub)?; + let anon_reg_sub = self.tcx.is_suitable_region(sub)?; let scope_def_id_sup = anon_reg_sup.def_id; let bregion_sup = anon_reg_sup.boundregion; let scope_def_id_sub = anon_reg_sub.def_id; diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs index e3faf755672..10a2d179dd5 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -36,7 +36,7 @@ pub(super) fn find_anon_type( region: Region<'tcx>, br: &ty::BoundRegion, ) -> Option<(&hir::Ty, &hir::FnDecl)> { - if let Some(anon_reg) = self.is_suitable_region(region) { + if let Some(anon_reg) = self.tcx.is_suitable_region(region) { let def_id = anon_reg.def_id; if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { let fndecl = match self.tcx.hir.get(node_id) { diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 4e26a4178b9..6ff008919e5 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -13,6 +13,7 @@ use infer::error_reporting::nice_region_error::NiceRegionError; use ty; use util::common::ErrorReported; +use errors::Applicability; impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and @@ -33,23 +34,23 @@ pub(super) fn try_report_named_anon_conflict(&self) -> Option { // version new_ty of its type where the anonymous region is replaced // with the named one.//scope_def_id let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub) - && self.is_suitable_region(sup).is_some() + && self.tcx.is_suitable_region(sup).is_some() && self.find_arg_with_region(sup, sub).is_some() { ( sub, sup, self.find_arg_with_region(sup, sub).unwrap(), - self.is_suitable_region(sup).unwrap(), + self.tcx.is_suitable_region(sup).unwrap(), ) - } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some() + } else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some() && self.find_arg_with_region(sub, sup).is_some() { ( sup, sub, self.find_arg_with_region(sub, sup).unwrap(), - self.is_suitable_region(sub).unwrap(), + self.tcx.is_suitable_region(sub).unwrap(), ) } else { return None; // inapplicable @@ -111,13 +112,14 @@ pub(super) fn try_report_named_anon_conflict(&self) -> Option { E0621, "explicit lifetime required in {}", error_var - ).span_suggestion( + ).span_suggestion_with_applicability( new_ty_span, &format!("add explicit lifetime `{}` to {}", named, span_label_var), - new_ty.to_string() + new_ty.to_string(), + Applicability::Unspecified, ) - .span_label(span, format!("lifetime `{}` required", named)) - .emit(); + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); return Some(ErrorReported); } diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index d25dcd5b045..3393eb65089 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -14,6 +14,7 @@ use infer::lexical_region_resolve::RegionResolutionError; use ty::{BoundRegion, FreeRegion, RegionKind}; use util::common::ErrorReported; +use errors::Applicability; impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. @@ -27,9 +28,9 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { sup_origin, sup_r, ) => { - let anon_reg_sup = self.is_suitable_region(sup_r)?; + let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?; if sub_r == &RegionKind::ReStatic && - self.is_return_type_impl_trait(anon_reg_sup.def_id) + self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some() { let sp = var_origin.span(); let return_sp = sub_origin.span(); @@ -61,7 +62,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { _ => "'_".to_owned(), }; if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) { - err.span_suggestion( + err.span_suggestion_with_applicability( return_sp, &format!( "you can add a constraint to the return type to make it last \ @@ -69,6 +70,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { lifetime, ), format!("{} + {}", snippet, lifetime_name), + Applicability::Unspecified, ); } err.emit(); diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 30406f1fec5..afc50fe1151 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -15,7 +15,6 @@ use infer::error_reporting::nice_region_error::NiceRegionError; use ty::{self, Region, Ty}; use hir::def_id::DefId; -use hir::Node; use syntax_pos::Span; // The struct contains the information about the anonymous region @@ -35,18 +34,6 @@ pub(super) struct AnonymousArgInfo<'tcx> { pub is_first: bool, } -// This struct contains information regarding the -// Refree((FreeRegion) corresponding to lifetime conflict -#[derive(Debug)] -pub(super) struct FreeRegionInfo { - // def id corresponding to FreeRegion - pub def_id: DefId, - // the bound region corresponding to FreeRegion - pub boundregion: ty::BoundRegion, - // checks if bound region is in Impl Item - pub is_impl_item: bool, -} - impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // This method walks the Type of the function body arguments using // `fold_regions()` function and returns the @@ -122,36 +109,6 @@ pub(super) fn find_arg_with_region( } } - // This method returns the DefId and the BoundRegion corresponding to the given region. - pub(super) fn is_suitable_region(&self, region: Region<'tcx>) -> Option { - let (suitable_region_binding_scope, bound_region) = match *region { - ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), - ty::ReEarlyBound(ref ebr) => ( - self.tcx.parent_def_id(ebr.def_id).unwrap(), - ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), - ), - _ => return None, // not a free region - }; - - let node_id = self.tcx - .hir - .as_local_node_id(suitable_region_binding_scope) - .unwrap(); - let is_impl_item = match self.tcx.hir.find(node_id) { - Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false, - Some(Node::ImplItem(..)) => { - self.is_bound_region_in_impl_item(suitable_region_binding_scope) - } - _ => return None, - }; - - return Some(FreeRegionInfo { - def_id: suitable_region_binding_scope, - boundregion: bound_region, - is_impl_item: is_impl_item, - }); - } - // Here, we check for the case where the anonymous region // is in the return type. // FIXME(#42703) - Need to handle certain cases here. @@ -176,22 +133,6 @@ pub(super) fn is_return_type_anon( None } - pub(super) fn is_return_type_impl_trait( - &self, - scope_def_id: DefId, - ) -> bool { - let ret_ty = self.tcx.type_of(scope_def_id); - match ret_ty.sty { - ty::FnDef(_, _) => { - let sig = ret_ty.fn_sig(self.tcx); - let output = self.tcx.erase_late_bound_regions(&sig.output()); - return output.is_impl_trait(); - } - _ => {} - } - false - } - // Here we check for the case where anonymous region // corresponds to self and if yes, we display E0312. // FIXME(#42700) - Need to format self properly to @@ -203,24 +144,4 @@ pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool { .map(|i| i.method_has_self_argument) == Some(true) } - // Here we check if the bound region is in Impl Item. - pub(super) fn is_bound_region_in_impl_item( - &self, - suitable_region_binding_scope: DefId, - ) -> bool { - let container_id = self.tcx - .associated_item(suitable_region_binding_scope) - .container - .id(); - if self.tcx.impl_trait_ref(container_id).is_some() { - // For now, we do not try to target impls of traits. This is - // because this message is going to suggest that the user - // change the fn signature, but they may not be free to do so, - // since the signature must match the trait. - // - // FIXME(#42706) -- in some cases, we could do better here. - return true; - } - false - } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c017c90b895..2eaf1eebb39 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -73,7 +73,7 @@ #![cfg_attr(not(stage0), feature(impl_header_lifetime_elision))] #![feature(in_band_lifetimes)] #![feature(macro_at_most_once_rep)] -#![feature(crate_in_paths)] +#![cfg_attr(stage0, feature(crate_in_paths))] #![feature(crate_visibility_modifier)] #![recursion_limit="512"] diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 356992b2214..469ae04c0fd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -317,7 +317,11 @@ pub fn consume_body(&mut self, body: &hir::Body) { debug!("consume_body: arg_ty = {:?}", arg_ty); let fn_body_scope_r = - self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id))); + self.tcx().mk_region(ty::ReScope( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node + })); let arg_cmt = Rc::new(self.mc.cat_rvalue( arg.hir_id, arg.pat.span, @@ -558,7 +562,10 @@ fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) { _ => { if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) { let def_id = def.def_id(); - let call_scope = region::Scope::Node(call.hir_id.local_id); + let call_scope = region::Scope { + id: call.hir_id.local_id, + data: region::ScopeData::Node + }; match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); @@ -766,7 +773,10 @@ fn walk_autoref(&mut self, // treated as borrowing it for the enclosing temporary // scope. let r = self.tcx().mk_region(ty::ReScope( - region::Scope::Node(expr.hir_id.local_id))); + region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); self.delegate.borrow(expr.id, expr.span, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index c34a0a654e6..13847fb48ce 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -64,10 +64,10 @@ //! methods. It effectively does a reverse walk of the AST; whenever we //! reach a loop node, we iterate until a fixed point is reached. //! -//! ## The `Users` struct +//! ## The `users_*` fields //! //! At each live node `N`, we track three pieces of information for each -//! variable `V` (these are encapsulated in the `Users` struct): +//! variable `V` (these are in the `users_*` fields): //! //! - `reader`: the `LiveNode` ID of some node which will read the value //! that `V` holds on entry to `N`. Formally: a node `M` such @@ -536,21 +536,6 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { // Actually we compute just a bit more than just liveness, but we use // the same basic propagation framework in all cases. -#[derive(Clone, Copy)] -struct Users { - reader: LiveNode, - writer: LiveNode, - used: bool -} - -fn invalid_users() -> Users { - Users { - reader: invalid_node(), - writer: invalid_node(), - used: false - } -} - #[derive(Copy, Clone)] struct Specials { exit_ln: LiveNode, @@ -567,7 +552,14 @@ struct Liveness<'a, 'tcx: 'a> { tables: &'a ty::TypeckTables<'tcx>, s: Specials, successors: Vec, - users: Vec, + + // We used to have a single `users: Vec` field here, where `Users` + // had `reader`, `writer` and `used` fields. But the number of users can + // get very large, and it's more compact to store the data in three + // separate `Vec`s so that no space is wasted for padding. + users_reader: Vec, + users_writer: Vec, + users_used: Vec, // mappings from loop node ID to LiveNode // ("break" label should map to loop node ID, @@ -592,13 +584,16 @@ fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> { let num_live_nodes = ir.num_live_nodes; let num_vars = ir.num_vars; + let num_users = num_live_nodes * num_vars; Liveness { ir, tables, s: specials, successors: vec![invalid_node(); num_live_nodes], - users: vec![invalid_users(); num_live_nodes * num_vars], + users_reader: vec![invalid_node(); num_users], + users_writer: vec![invalid_node(); num_users], + users_used: vec![false; num_users], break_ln: NodeMap(), cont_ln: NodeMap(), } @@ -665,7 +660,7 @@ fn idx(&self, ln: LiveNode, var: Variable) -> usize { fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option { assert!(ln.is_valid()); - let reader = self.users[self.idx(ln, var)].reader; + let reader = self.users_reader[self.idx(ln, var)]; if reader.is_valid() {Some(self.ir.lnk(reader))} else {None} } @@ -680,13 +675,13 @@ fn live_on_exit(&self, ln: LiveNode, var: Variable) fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool { assert!(ln.is_valid()); - self.users[self.idx(ln, var)].used + self.users_used[self.idx(ln, var)] } fn assigned_on_entry(&self, ln: LiveNode, var: Variable) -> Option { assert!(ln.is_valid()); - let writer = self.users[self.idx(ln, var)].writer; + let writer = self.users_writer[self.idx(ln, var)]; if writer.is_valid() {Some(self.ir.lnk(writer))} else {None} } @@ -730,9 +725,9 @@ fn ln_str(&self, ln: LiveNode) -> String { { let wr = &mut wr as &mut dyn Write; write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln)); - self.write_vars(wr, ln, |idx| self.users[idx].reader); + self.write_vars(wr, ln, |idx| self.users_reader[idx]); write!(wr, " writes"); - self.write_vars(wr, ln, |idx| self.users[idx].writer); + self.write_vars(wr, ln, |idx| self.users_writer[idx]); write!(wr, " precedes {:?}]", self.successors[ln.get()]); } String::from_utf8(wr).unwrap() @@ -747,7 +742,9 @@ fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) { // only grow during iterations. // // self.indices(ln) { |idx| - // self.users[idx] = invalid_users(); + // self.users_reader[idx] = invalid_node(); + // self.users_writer[idx] = invalid_node(); + // self.users_used[idx] = false; // } } @@ -756,7 +753,9 @@ fn init_from_succ(&mut self, ln: LiveNode, succ_ln: LiveNode) { self.successors[ln.get()] = succ_ln; self.indices2(ln, succ_ln, |this, idx, succ_idx| { - this.users[idx] = this.users[succ_idx] + this.users_reader[idx] = this.users_reader[succ_idx]; + this.users_writer[idx] = this.users_writer[succ_idx]; + this.users_used[idx] = this.users_used[succ_idx]; }); debug!("init_from_succ(ln={}, succ={})", self.ln_str(ln), self.ln_str(succ_ln)); @@ -771,12 +770,10 @@ fn merge_from_succ(&mut self, let mut changed = false; self.indices2(ln, succ_ln, |this, idx, succ_idx| { - changed |= copy_if_invalid(this.users[succ_idx].reader, - &mut this.users[idx].reader); - changed |= copy_if_invalid(this.users[succ_idx].writer, - &mut this.users[idx].writer); - if this.users[succ_idx].used && !this.users[idx].used { - this.users[idx].used = true; + changed |= copy_if_invalid(this.users_reader[succ_idx], &mut this.users_reader[idx]); + changed |= copy_if_invalid(this.users_writer[succ_idx], &mut this.users_writer[idx]); + if this.users_used[succ_idx] && !this.users_used[idx] { + this.users_used[idx] = true; changed = true; } }); @@ -800,8 +797,8 @@ fn copy_if_invalid(src: LiveNode, dst: &mut LiveNode) -> bool { // this) so we just clear out all the data. fn define(&mut self, writer: LiveNode, var: Variable) { let idx = self.idx(writer, var); - self.users[idx].reader = invalid_node(); - self.users[idx].writer = invalid_node(); + self.users_reader[idx] = invalid_node(); + self.users_writer[idx] = invalid_node(); debug!("{:?} defines {:?} (idx={}): {}", writer, var, idx, self.ln_str(writer)); @@ -813,21 +810,20 @@ fn acc(&mut self, ln: LiveNode, var: Variable, acc: u32) { ln, acc, var, self.ln_str(ln)); let idx = self.idx(ln, var); - let user = &mut self.users[idx]; if (acc & ACC_WRITE) != 0 { - user.reader = invalid_node(); - user.writer = ln; + self.users_reader[idx] = invalid_node(); + self.users_writer[idx] = ln; } // Important: if we both read/write, must do read second // or else the write will override. if (acc & ACC_READ) != 0 { - user.reader = ln; + self.users_reader[idx] = ln; } if (acc & ACC_USE) != 0 { - user.used = true; + self.users_used[idx] = true; } } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2f99743cfbd..788fbcef171 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -102,8 +102,8 @@ /// generated via deriving here. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)] pub struct Scope { - pub(crate) id: hir::ItemLocalId, - pub(crate) data: ScopeData, + pub id: hir::ItemLocalId, + pub data: ScopeData, } impl fmt::Debug for Scope { @@ -172,48 +172,6 @@ pub struct FirstStatementIndex { .. } #[cfg(not(stage0))] static ASSERT: () = [()][!(mem::size_of::() == 4) as usize]; -#[allow(non_snake_case)] -impl Scope { - #[inline] - pub fn data(self) -> ScopeData { - self.data - } - - #[inline] - pub fn new(id: hir::ItemLocalId, data: ScopeData) -> Self { - Scope { id, data } - } - - #[inline] - pub fn Node(id: hir::ItemLocalId) -> Self { - Self::new(id, ScopeData::Node) - } - - #[inline] - pub fn CallSite(id: hir::ItemLocalId) -> Self { - Self::new(id, ScopeData::CallSite) - } - - #[inline] - pub fn Arguments(id: hir::ItemLocalId) -> Self { - Self::new(id, ScopeData::Arguments) - } - - #[inline] - pub fn Destruction(id: hir::ItemLocalId) -> Self { - Self::new(id, ScopeData::Destruction) - } - - #[inline] - pub fn Remainder( - id: hir::ItemLocalId, - first: FirstStatementIndex, - ) -> Self { - Self::new(id, ScopeData::Remainder(first)) - } -} - - impl Scope { /// Returns a item-local id associated with this scope. /// @@ -244,7 +202,7 @@ pub fn span(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> Span { return DUMMY_SP; } let span = tcx.hir.span(node_id); - if let ScopeData::Remainder(first_statement_index) = self.data() { + if let ScopeData::Remainder(first_statement_index) = self.data { if let Node::Block(ref blk) = tcx.hir.get(node_id) { // Want span for scope starting after the // indexed statement and ending at end of @@ -498,7 +456,7 @@ pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, Scope } // record the destruction scopes for later so we can query them - if let ScopeData::Destruction = child.data() { + if let ScopeData::Destruction = child.data { self.destruction_scopes.insert(child.item_local_id(), child); } } @@ -578,10 +536,10 @@ pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option { // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. - let mut id = Scope::Node(expr_id); + let mut id = Scope { id: expr_id, data: ScopeData::Node }; while let Some(&(p, _)) = self.parent_map.get(&id) { - match p.data() { + match p.data { ScopeData::Destruction => { debug!("temporary_scope({:?}) = {:?} [enclosing]", expr_id, id); @@ -637,7 +595,7 @@ pub fn is_subscope_of(&self, /// Returns the id of the innermost containing body pub fn containing_body(&self, mut scope: Scope)-> Option { loop { - if let ScopeData::CallSite = scope.data() { + if let ScopeData::CallSite = scope.data { return Some(scope.item_local_id()); } @@ -730,7 +688,7 @@ pub fn early_free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self.root_body.unwrap().local_id }); - Scope::CallSite(scope) + Scope { id: scope, data: ScopeData::CallSite } } /// Assuming that the provided region was defined within this `ScopeTree`, @@ -750,7 +708,7 @@ pub fn free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeReg let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); let body_id = tcx.hir.body_owned_by(param_owner_id); - Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) + Scope { id: tcx.hir.body(body_id).value.hir_id.local_id, data: ScopeData::CallSite } } /// Checks whether the given scope contains a `yield`. If so, @@ -854,7 +812,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // except for the first such subscope, which has the // block itself as a parent. visitor.enter_scope( - Scope::Remainder(blk.hir_id.local_id, FirstStatementIndex::new(i)) + Scope { + id: blk.hir_id.local_id, + data: ScopeData::Remainder(FirstStatementIndex::new(i)) + } ); visitor.cx.var_parent = visitor.cx.parent; } @@ -879,7 +840,7 @@ fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: & } fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) { - visitor.record_child_scope(Scope::Node(pat.hir_id.local_id)); + visitor.record_child_scope(Scope { id: pat.hir_id.local_id, data: ScopeData::Node }); // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.node { @@ -1008,7 +969,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: if let hir::ExprKind::Yield(..) = expr.node { // Mark this expr's scope and all parent scopes as containing `yield`. - let mut scope = Scope::Node(expr.hir_id.local_id); + let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; loop { visitor.scope_tree.yield_in_scope.insert(scope, (expr.span, visitor.expr_and_pat_count)); @@ -1016,7 +977,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: // Keep traversing up while we can. match visitor.scope_tree.parent_map.get(&scope) { // Don't cross from closure bodies to their parent. - Some(&(superscope, _)) => match superscope.data() { + Some(&(superscope, _)) => match superscope.data { ScopeData::CallSite => break, _ => scope = superscope }, @@ -1280,9 +1241,9 @@ fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) { // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. if self.terminating_scopes.contains(&id) { - self.enter_scope(Scope::Destruction(id)); + self.enter_scope(Scope { id, data: ScopeData::Destruction }); } - self.enter_scope(Scope::Node(id)); + self.enter_scope(Scope { id, data: ScopeData::Node }); } } @@ -1315,8 +1276,8 @@ fn visit_body(&mut self, body: &'tcx hir::Body) { } self.cx.root_id = Some(body.value.hir_id.local_id); - self.enter_scope(Scope::CallSite(body.value.hir_id.local_id)); - self.enter_scope(Scope::Arguments(body.value.hir_id.local_id)); + self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); + self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index c919793fe3e..db1bc3e7519 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use super::*; @@ -32,7 +32,7 @@ #[derive(Clone)] pub struct Preorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, - visited: BitArray, + visited: BitSet, worklist: Vec, } @@ -42,7 +42,7 @@ pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> { Preorder { mir, - visited: BitArray::new(mir.basic_blocks().len()), + visited: BitSet::new_empty(mir.basic_blocks().len()), worklist, } } @@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} /// A Postorder traversal of this graph is `D B C A` or `D C B A` pub struct Postorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, - visited: BitArray, + visited: BitSet, visit_stack: Vec<(BasicBlock, Successors<'a>)> } @@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> { let mut po = Postorder { mir, - visited: BitArray::new(mir.basic_blocks().len()), + visited: BitSet::new_empty(mir.basic_blocks().len()), visit_stack: Vec::new() }; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2a9732bf02c..e4d633c3f2c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -275,18 +275,18 @@ pub fn should_codegen(&self) -> bool { // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That // would break dependency tracking for commandline arguments. #[derive(Clone, Hash)] -pub struct Externs(BTreeMap>); +pub struct Externs(BTreeMap>>); impl Externs { - pub fn new(data: BTreeMap>) -> Externs { + pub fn new(data: BTreeMap>>) -> Externs { Externs(data) } - pub fn get(&self, key: &str) -> Option<&BTreeSet> { + pub fn get(&self, key: &str) -> Option<&BTreeSet>> { self.0.get(key) } - pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet> { + pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet>> { self.0.iter() } } @@ -1331,6 +1331,8 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool { "disable user provided type assertion in NLL"), nll_dont_emit_read_for_match: bool = (false, parse_bool, [UNTRACKED], "in match codegen, do not include ReadForMatch statements (used by mir-borrowck)"), + dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED], + "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting)."), polonius: bool = (false, parse_bool, [UNTRACKED], "enable polonius-based borrow-checker"), codegen_time_graph: bool = (false, parse_bool, [UNTRACKED], @@ -2169,6 +2171,8 @@ pub fn build_session_options_and_crate_config( let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); + let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, @@ -2182,15 +2186,13 @@ pub fn build_session_options_and_crate_config( "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "target-spec-json" => { - if nightly_options::is_unstable_enabled(matches) { + if is_unstable_enabled { PrintRequest::TargetSpec } else { early_error( error_format, - &format!( - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option" - ), + "the `-Z unstable-options` flag must also be passed to \ + enable the target-spec-json print option", ); } } @@ -2220,18 +2222,19 @@ pub fn build_session_options_and_crate_config( Some(s) => s, None => early_error(error_format, "--extern value must not be empty"), }; - let location = match parts.next() { - Some(s) => s, - None => early_error( + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !is_unstable_enabled { + early_error( error_format, - "--extern value must be of the format `foo=bar`", - ), + "the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`", + ); }; externs .entry(name.to_string()) .or_default() - .insert(location.to_string()); + .insert(location); } let crate_name = matches.opt_str("crate-name"); @@ -2687,33 +2690,33 @@ fn test_externs_tracking_hash_different_construction_order() { v1.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ])); v2.externs = Externs::new(mk_map(vec![ ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ])); v3.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("f"), String::from("e")]), + mk_set(vec![Some(String::from("f")), Some(String::from("e"))]), ), ])); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 619262abb0b..7bf0d8ecec8 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -28,7 +28,7 @@ use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock}; use syntax::ast::NodeId; -use errors::{self, DiagnosticBuilder, DiagnosticId}; +use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability}; use errors::emitter::{Emitter, EmitterWriter}; use syntax::edition::Edition; use syntax::json::JsonEmitter; @@ -431,8 +431,13 @@ fn diag_once<'a, 'b>( diag_builder.span_note(span, message); } DiagnosticBuilderMethod::SpanSuggestion(suggestion) => { - let span = span_maybe.expect("span_suggestion needs a span"); - diag_builder.span_suggestion(span, message, suggestion); + let span = span_maybe.expect("span_suggestion_* needs a span"); + diag_builder.span_suggestion_with_applicability( + span, + message, + suggestion, + Applicability::Unspecified, + ); } } } @@ -1012,6 +1017,7 @@ pub fn build_session_with_source_map( let can_emit_warnings = !(warnings_allow || cap_lints_allow); let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug; + let dont_buffer_diagnostics = sopts.debugging_opts.dont_buffer_diagnostics; let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs; let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace; @@ -1059,6 +1065,7 @@ pub fn build_session_with_source_map( can_emit_warnings, treat_err_as_bug, report_delayed_bugs, + dont_buffer_diagnostics, external_macro_backtrace, ..Default::default() }, diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index ed95aa73078..4bed3c5935c 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -112,6 +112,7 @@ pub fn find_auto_trait_generics( orig_params, trait_pred.to_poly_trait_predicate(), )); + match result { Ok(Some(Vtable::VtableImpl(_))) => { debug!( @@ -119,10 +120,10 @@ pub fn find_auto_trait_generics( manual impl found, bailing out", did, trait_did, generics ); - return true; + true } - _ => return false, - }; + _ => false + } }); // If an explicit impl exists, it always takes priority over an auto impl @@ -426,6 +427,7 @@ fn add_user_pred<'c>(&self, user_computed_preds: &mut FxHashSet Option { pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap) -> String { self.region_name(region) - .map(|name| { - names_map.get(&name).unwrap_or_else(|| { + .map(|name| + names_map.get(&name).unwrap_or_else(|| panic!("Missing lifetime with name {:?} for {:?}", name, region) - }) - }) - .unwrap_or(&"'static".to_string()) + ) + ) + .unwrap_or(&"'static".to_owned()) .clone() } diff --git a/src/librustc/traits/codegen/mod.rs b/src/librustc/traits/codegen/mod.rs index cf404202ac1..4e88150a18a 100644 --- a/src/librustc/traits/codegen/mod.rs +++ b/src/librustc/traits/codegen/mod.rs @@ -39,7 +39,7 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, let trait_ref = ty.erase_regions(&trait_ref); debug!("codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})", - (param_env, trait_ref), trait_ref.def_id()); + (param_env, trait_ref), trait_ref.def_id()); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. @@ -48,8 +48,8 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, let obligation_cause = ObligationCause::dummy(); let obligation = Obligation::new(obligation_cause, - param_env, - trait_ref.to_poly_trait_predicate()); + param_env, + trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, @@ -61,12 +61,11 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, // overflow bug, since I believe this is the only case // where ambiguity can result. bug!("Encountered ambiguity selecting `{:?}` during codegen, \ - presuming due to overflow", - trait_ref) + presuming due to overflow", + trait_ref) } Err(e) => { - bug!("Encountered error `{:?}` selecting `{:?}` during codegen", - e, trait_ref) + bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } }; @@ -163,22 +162,16 @@ fn drain_fulfillment_cx_or_panic(&self, // In principle, we only need to do this so long as `result` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - match fulfill_cx.select_all_or_error(self) { - Ok(()) => { } - Err(errors) => { - span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking", - errors); - } + if let Err(errors) = fulfill_cx.select_all_or_error(self) { + span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking", + errors); } let result = self.resolve_type_vars_if_possible(result); let result = self.tcx.erase_regions(&result); - match self.tcx.lift_to_global(&result) { - Some(result) => result, - None => { - span_bug!(span, "Uninferred types/regions in `{:?}`", result); - } - } + self.tcx.lift_to_global(&result).unwrap_or_else(|| + span_bug!(span, "Uninferred types/regions in `{:?}`", result) + ) } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b8dd2a12fb5..251743b0d3b 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -115,9 +115,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, b_def_id: DefId) -> Option> { - debug!("overlap(a_def_id={:?}, b_def_id={:?})", - a_def_id, - b_def_id); + debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); // For the purposes of this check, we don't bring any skolemized // types into scope; instead, we replace the generic types with @@ -133,10 +131,9 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, // Do `a` and `b` unify? If not, no overlap. let obligations = match selcx.infcx().at(&ObligationCause::dummy(), param_env) - .eq_impl_headers(&a_impl_header, &b_impl_header) { - Ok(InferOk { obligations, value: () }) => { - obligations - } + .eq_impl_headers(&a_impl_header, &b_impl_header) + { + Ok(InferOk { obligations, value: () }) => obligations, Err(_) => return None }; @@ -164,7 +161,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, return None } - let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); + let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) @@ -471,14 +468,12 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool { ty::Foreign(did) => def_id_is_local(did, in_crate), ty::Dynamic(ref tt, ..) => { - tt.principal().map_or(false, |p| { + tt.principal().map_or(false, |p| def_id_is_local(p.def_id(), in_crate) - }) + ) } - ty::Error => { - true - } + ty::Error => true, ty::Closure(..) | ty::Generator(..) | diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 466d472cca3..6fb5acde72c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -34,6 +34,7 @@ use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use std::fmt; +use std::iter; use syntax::ast; use session::DiagnosticMessageId; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; @@ -58,7 +59,7 @@ struct ErrorDescriptor<'tcx> { index: Option, // None if this is an old error } - let mut error_map : FxHashMap<_, Vec<_>> = + let mut error_map: FxHashMap<_, Vec<_>> = self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| { (span, predicates.iter().map(|predicate| ErrorDescriptor { predicate: predicate.clone(), @@ -80,7 +81,7 @@ struct ErrorDescriptor<'tcx> { // We do this in 2 passes because we want to display errors in order, tho // maybe it *is* better to sort errors by span or something. - let mut is_suppressed: Vec = errors.iter().map(|_| false).collect(); + let mut is_suppressed = vec![false; errors.len()]; for (_, error_set) in error_map.iter() { // We want to suppress "duplicate" errors with the same span. for error in error_set { @@ -349,7 +350,7 @@ fn on_unimplemented_note( _ => { // this is a "direct", user-specified, rather than derived, // obligation. - flags.push(("direct".to_string(), None)); + flags.push(("direct".to_owned(), None)); } } @@ -361,24 +362,24 @@ fn on_unimplemented_note( // Currently I'm leaving it for what I need for `try`. if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { let method = self.tcx.item_name(item); - flags.push(("from_method".to_string(), None)); - flags.push(("from_method".to_string(), Some(method.to_string()))); + flags.push(("from_method".to_owned(), None)); + flags.push(("from_method".to_owned(), Some(method.to_string()))); } } if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { - flags.push(("from_desugaring".to_string(), None)); - flags.push(("from_desugaring".to_string(), Some(k.name().to_string()))); + flags.push(("from_desugaring".to_owned(), None)); + flags.push(("from_desugaring".to_owned(), Some(k.name().to_string()))); } let generics = self.tcx.generics_of(def_id); let self_ty = trait_ref.self_ty(); // This is also included through the generics list as `Self`, // but the parser won't allow you to use it - flags.push(("_Self".to_string(), Some(self_ty.to_string()))); + flags.push(("_Self".to_owned(), Some(self_ty.to_string()))); if let Some(def) = self_ty.ty_adt_def() { // We also want to be able to select self's original // signature with no type arguments resolved - flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string()))); + flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string()))); } for param in generics.params.iter() { @@ -393,7 +394,7 @@ fn on_unimplemented_note( } if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push(("crate_local".to_string(), None)); + flags.push(("crate_local".to_owned(), None)); } if let Ok(Some(command)) = OnUnimplementedDirective::of_item( @@ -412,27 +413,26 @@ fn find_similar_impl_candidates(&self, let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); - let mut impl_candidates = Vec::new(); + let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { - Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { + Some(simp) => all_impls.iter().filter_map(|&def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); if let Some(imp_simp) = imp_simp { if simp != imp_simp { - return; + return None } } - impl_candidates.push(imp); - }), - None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { - impl_candidates.push( - self.tcx.impl_trait_ref(def_id).unwrap()); - }) - }; - impl_candidates + + Some(imp) + }).collect(), + None => all_impls.iter().map(|&def_id| + self.tcx.impl_trait_ref(def_id).unwrap() + ).collect() + } } fn report_similar_impl_candidates(&self, @@ -603,10 +603,10 @@ pub fn report_selection_error(&self, span, E0277, "{}", - message.unwrap_or_else(|| { + message.unwrap_or_else(|| format!("the trait bound `{}` is not satisfied{}", trait_ref.to_predicate(), post_message) - })); + )); let explanation = if obligation.cause.code == ObligationCauseCode::MainFunctionType { @@ -645,7 +645,7 @@ pub fn report_selection_error(&self, // "the type `T` can't be frobnicated" // which is somewhat confusing. err.help(&format!("consider adding a `where {}` bound", - trait_ref.to_predicate())); + trait_ref.to_predicate())); } else if !have_alt_message { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_ref); @@ -693,7 +693,7 @@ pub fn report_selection_error(&self, ty::Predicate::RegionOutlives(ref predicate) => { let predicate = self.resolve_type_vars_if_possible(predicate); let err = self.region_outlives_predicate(&obligation.cause, - &predicate).err().unwrap(); + &predicate).err().unwrap(); struct_span_err!(self.tcx.sess, span, E0279, "the requirement `{}` is not satisfied (`{}`)", predicate, err) @@ -722,7 +722,7 @@ pub fn report_selection_error(&self, let mut err = struct_span_err!( self.tcx.sess, closure_span, E0525, "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", + but this closure only implements `{}`", kind, found_kind); @@ -779,40 +779,34 @@ pub fn report_selection_error(&self, OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref); let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); + if expected_trait_ref.self_ty().references_error() { return; } + let found_trait_ty = found_trait_ref.self_ty(); let found_did = match found_trait_ty.sty { - ty::Closure(did, _) | - ty::Foreign(did) | - ty::FnDef(did, _) => Some(did), + ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), ty::Adt(def, _) => Some(def.did), _ => None, }; - let found_span = found_did.and_then(|did| { + + let found_span = found_did.and_then(|did| self.tcx.hir.span_if_local(did) - }).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def + ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def let found = match found_trait_ref.skip_binder().substs.type_at(1).sty { - ty::Tuple(ref tys) => tys.iter() - .map(|_| ArgKind::empty()).collect::>(), + ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], _ => vec![ArgKind::empty()], }; + let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty { ty::Tuple(ref tys) => tys.iter() - .map(|t| match t.sty { - ty::Tuple(ref tys) => ArgKind::Tuple( - Some(span), - tys.iter() - .map(|ty| ("_".to_owned(), ty.sty.to_string())) - .collect::>() - ), - _ => ArgKind::Arg("_".to_owned(), t.sty.to_string()), - }).collect(), + .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(), ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())], }; + if found.len() == expected.len() { self.report_closure_arg_mismatch(span, found_span, @@ -836,8 +830,7 @@ pub fn report_selection_error(&self, TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); - self.tcx.report_object_safety_error(span, did, - violations) + self.tcx.report_object_safety_error(span, did, violations) } ConstEvalFailure(ref err) => { @@ -846,7 +839,11 @@ pub fn report_selection_error(&self, "could not evaluate constant expression", ) { Some(err) => err, - None => return, + None => { + self.tcx.sess.delay_span_bug(span, + &format!("constant in type had an ignored error: {:?}", err)); + return; + } } } @@ -981,11 +978,9 @@ pub fn get_fn_like_arguments(&self, node: Node) -> (Span, Vec) { .map(|arg| match arg.clone().node { hir::TyKind::Tup(ref tys) => ArgKind::Tuple( Some(arg.span), - tys.iter() - .map(|_| ("_".to_owned(), "_".to_owned())) - .collect::>(), + vec![("_".to_owned(), "_".to_owned()); tys.len()] ), - _ => ArgKind::Arg("_".to_owned(), "_".to_owned()) + _ => ArgKind::empty() }).collect::>()) } Node::Variant(&hir::Variant { @@ -997,15 +992,13 @@ pub fn get_fn_like_arguments(&self, node: Node) -> (Span, Vec) { .. }) => { (self.tcx.sess.source_map().def_span(span), - fields.iter().map(|field| { + fields.iter().map(|field| ArgKind::Arg(field.ident.to_string(), "_".to_string()) - }).collect::>()) + ).collect::>()) } Node::StructCtor(ref variant_data) => { (self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())), - variant_data.fields() - .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned())) - .collect()) + vec![ArgKind::empty(); variant_data.fields().len()]) } _ => panic!("non-FnLike node found: {:?}", node), } @@ -1054,7 +1047,7 @@ pub fn report_arg_count_mismatch( found_str, ); - err.span_label(span, format!( "expected {} that takes {}", kind, expected_str)); + err.span_label(span, format!("expected {} that takes {}", kind, expected_str)); if let Some(found_span) = found_span { err.span_label(found_span, format!("takes {}", found_str)); @@ -1063,9 +1056,8 @@ pub fn report_arg_count_mismatch( // found arguments is empty (assume the user just wants to ignore args in this case). // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { - let underscores = "_".repeat(expected_args.len()) - .split("") - .filter(|s| !s.is_empty()) + let underscores = iter::repeat("_") + .take(expected_args.len()) .collect::>() .join(", "); err.span_suggestion_with_applicability( @@ -1087,7 +1079,8 @@ pub fn report_arg_count_mismatch( if fields.len() == expected_args.len() { let sugg = fields.iter() .map(|(name, _)| name.to_owned()) - .collect::>().join(", "); + .collect::>() + .join(", "); err.span_suggestion_with_applicability(found_span, "change the closure to take multiple \ arguments instead of a single tuple", @@ -1146,7 +1139,7 @@ fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, let inputs = trait_ref.substs.type_at(1); let sig = if let ty::Tuple(inputs) = inputs.sty { tcx.mk_fn_sig( - inputs.iter().map(|&x| x), + inputs.iter().cloned(), tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), false, hir::Unsafety::Normal, @@ -1220,10 +1213,9 @@ pub fn report_object_safety_error(self, let mut reported_violations = FxHashSet(); for violation in violations { - if !reported_violations.insert(violation.clone()) { - continue; + if reported_violations.insert(violation.clone()) { + err.note(&violation.error_msg()); } - err.note(&violation.error_msg()); } err } @@ -1289,10 +1281,10 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, self.need_type_info_err(body_id, span, self_ty).emit(); } else { let mut err = struct_span_err!(self.tcx.sess, - span, E0283, - "type annotations required: \ + span, E0283, + "type annotations required: \ cannot resolve `{}`", - predicate); + predicate); self.note_obligation_cause(&mut err, obligation); err.emit(); } @@ -1438,6 +1430,7 @@ fn note_obligation_cause_code(&self, ObligationCauseCode::ItemObligation(item_def_id) => { let item_name = tcx.item_path_str(item_def_id); let msg = format!("required by `{}`", item_name); + if let Some(sp) = tcx.hir.span_if_local(item_def_id) { let sp = tcx.sess.source_map().def_span(sp); err.span_note(sp, &msg); @@ -1529,9 +1522,9 @@ fn note_obligation_cause_code(&self, parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); self.note_obligation_cause_code(err, - &parent_predicate, - &data.parent_code, - obligated_types); + &parent_predicate, + &data.parent_code, + obligated_types); } ObligationCauseCode::CompareImplMethodObligation { .. } => { err.note( @@ -1560,21 +1553,21 @@ fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { } fn is_recursive_obligation(&self, - obligated_types: &mut Vec<&ty::TyS<'tcx>>, - cause_code: &ObligationCauseCode<'tcx>) -> bool { + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + cause_code: &ObligationCauseCode<'tcx>) -> bool { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); - for obligated_type in obligated_types { - if obligated_type == &parent_trait_ref.skip_binder().self_ty() { - return true; - } + + if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { + return true; } } - return false; + false } } /// Summarizes information +#[derive(Clone)] pub enum ArgKind { /// An argument of non-tuple type. Parameters are (name, ty) Arg(String, String), @@ -1592,11 +1585,11 @@ fn empty() -> ArgKind { } /// Creates an `ArgKind` from the expected type of an - /// argument. This has no name (`_`) and no source spans.. - pub fn from_expected_ty(t: Ty<'_>) -> ArgKind { + /// argument. It has no name (`_`) and an optional source span. + pub fn from_expected_ty(t: Ty<'_>, span: Option) -> ArgKind { match t.sty { ty::Tuple(ref tys) => ArgKind::Tuple( - None, + span, tys.iter() .map(|ty| ("_".to_owned(), ty.sty.to_string())) .collect::>() diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 9998db4ad1d..707af02acbf 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -526,7 +526,7 @@ fn process_backedge<'c, I>(&mut self, cycle: I, if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) { debug!("process_child_obligations: coinductive match"); } else { - let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); + let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); self.selcx.infcx().report_overflow_error_cycle(&cycle); } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e2dbe883540..edf7772f2f7 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -661,7 +661,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let predicates: Vec<_> = util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) - .collect(); + .collect(); debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); @@ -707,7 +707,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; debug!("normalize_param_env_or_error: normalized predicates={:?}", - predicates); + predicates); let region_scope_tree = region::ScopeTree::default(); @@ -851,16 +851,16 @@ fn vtable_methods<'a, 'tcx>( // the method may have some early-bound lifetimes, add // regions for those - let substs = trait_ref.map_bound(|trait_ref| { - Substs::for_item(tcx, def_id, |param, _| { + let substs = trait_ref.map_bound(|trait_ref| + Substs::for_item(tcx, def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.types.re_erased.into(), GenericParamDefKind::Type {..} => { trait_ref.substs[param.index as usize] } } - }) - }); + ) + ); // the trait type may have higher-ranked lifetimes in it; // so erase them if they appear, so that we get the type diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 17d55b77625..0046a23a085 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -124,20 +124,21 @@ fn object_safety_violations_for_trait(self, trait_def_id: DefId) // Check methods for violations. let mut violations: Vec<_> = self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssociatedKind::Method) - .filter_map(|item| { + .filter_map(|item| self.object_safety_violation_for_method(trait_def_id, &item) .map(|code| ObjectSafetyViolation::Method(item.ident.name, code)) - }).filter(|violation| { + ).filter(|violation| { if let ObjectSafetyViolation::Method(_, - MethodViolationCode::WhereClauseReferencesSelf(span)) = violation { - // Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. + MethodViolationCode::WhereClauseReferencesSelf(span)) = violation + { + // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. // It's also hard to get a use site span, so we use the method definition span. self.lint_node_note( lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY, ast::CRATE_NODE_ID, *span, &format!("the trait `{}` cannot be made into an object", - self.item_path_str(trait_def_id)), + self.item_path_str(trait_def_id)), &violation.error_msg()); false } else { @@ -213,24 +214,23 @@ fn generics_require_sized_self(self, def_id: DefId) -> bool { let predicates = self.predicates_of(def_id); let predicates = predicates.instantiate_identity(self).predicates; elaborate_predicates(self, predicates) - .any(|predicate| { - match predicate { - ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { - trait_pred.skip_binder().self_ty().is_self() - } - ty::Predicate::Projection(..) | - ty::Predicate::Trait(..) | - ty::Predicate::Subtype(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::WellFormed(..) | - ty::Predicate::ObjectSafe(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::TypeOutlives(..) | - ty::Predicate::ConstEvaluatable(..) => { - false - } + .any(|predicate| match predicate { + ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { + trait_pred.skip_binder().self_ty().is_self() } - }) + ty::Predicate::Projection(..) | + ty::Predicate::Trait(..) | + ty::Predicate::Subtype(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::WellFormed(..) | + ty::Predicate::ObjectSafe(..) | + ty::Predicate::ClosureKind(..) | + ty::Predicate::TypeOutlives(..) | + ty::Predicate::ConstEvaluatable(..) => { + false + } + } + ) } /// Returns `Some(_)` if this method makes the containing trait not object safe. diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 280ce75720b..f59812c0eea 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -74,17 +74,17 @@ pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, let condition = if is_root { None } else { - let cond = item_iter.next().ok_or_else(|| { + let cond = item_iter.next().ok_or_else(|| parse_error(tcx, span, "empty `on`-clause in `#[rustc_on_unimplemented]`", "empty on-clause here", None) - })?.meta_item().ok_or_else(|| { + )?.meta_item().ok_or_else(|| parse_error(tcx, span, "invalid `on`-clause in `#[rustc_on_unimplemented]`", "invalid on-clause here", None) - })?; + )?; attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true); Some(cond.clone()) }; @@ -259,9 +259,9 @@ fn verify(&self, // `{from_desugaring}` is allowed Position::ArgumentNamed(s) if s == "from_desugaring" => (), // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { + Position::ArgumentNamed(s) => match generics.params.iter().find(|param| param.name == s - }) { + ) { Some(_) => (), None => { span_err!(tcx.sess, span, E0230, @@ -304,7 +304,7 @@ pub fn format(&self, let empty_string = String::new(); let parser = Parser::new(&self.0, None); - parser.map(|p| { + parser.map(|p| match p { Piece::String(s) => s, Piece::NextArgument(a) => match a.position { @@ -326,11 +326,9 @@ pub fn format(&self, } } }, - _ => { - bug!("broken on_unimplemented {:?} - bad format arg", self.0) - } + _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0) } } - }).collect() + ).collect() } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index e50f59cbc82..5ea936f750e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -171,7 +171,7 @@ fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool { match (current, candidate) { (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (), (ParamEnv(..), _) => return false, - (_, ParamEnv(..)) => { unreachable!(); } + (_, ParamEnv(..)) => unreachable!(), (_, _) => convert_to_ambiguous = (), } } @@ -419,9 +419,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { normalized_ty } - _ => { - ty - } + _ => ty } } @@ -437,12 +435,9 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc instance, promoted: None }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => { - let evaluated = evaluated.subst(self.tcx(), substs); - return self.fold_const(evaluated); - } - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + let evaluated = evaluated.subst(self.tcx(), substs); + return self.fold_const(evaluated); } } } else { @@ -453,9 +448,8 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc instance, promoted: None }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => return self.fold_const(evaluated), - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + return self.fold_const(evaluated) } } } @@ -993,7 +987,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( candidate_set.mark_ambiguous(); return; } - _ => { return; } + _ => return }; // If so, extract what we know from the trait and try to come up with a good answer. @@ -1023,33 +1017,30 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( for predicate in env_predicates { debug!("assemble_candidates_from_predicates: predicate={:?}", predicate); - match predicate { - ty::Predicate::Projection(data) => { - let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; - - let is_match = same_def_id && infcx.probe(|_| { - let data_poly_trait_ref = - data.to_poly_trait_ref(infcx.tcx); - let obligation_poly_trait_ref = - obligation_trait_ref.to_poly_trait_ref(); - infcx.at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .map(|InferOk { obligations: _, value: () }| { - // FIXME(#32730) -- do we need to take obligations - // into account in any way? At the moment, no. - }) - .is_ok() - }); - - debug!("assemble_candidates_from_predicates: candidate={:?} \ - is_match={} same_def_id={}", - data, is_match, same_def_id); - - if is_match { - candidate_set.push_candidate(ctor(data)); - } + if let ty::Predicate::Projection(data) = predicate { + let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; + + let is_match = same_def_id && infcx.probe(|_| { + let data_poly_trait_ref = + data.to_poly_trait_ref(infcx.tcx); + let obligation_poly_trait_ref = + obligation_trait_ref.to_poly_trait_ref(); + infcx.at(&obligation.cause, obligation.param_env) + .sup(obligation_poly_trait_ref, data_poly_trait_ref) + .map(|InferOk { obligations: _, value: () }| { + // FIXME(#32730) -- do we need to take obligations + // into account in any way? At the moment, no. + }) + .is_ok() + }); + + debug!("assemble_candidates_from_predicates: candidate={:?} \ + is_match={} same_def_id={}", + data, is_match, same_def_id); + + if is_match { + candidate_set.push_candidate(ctor(data)); } - _ => {} } } } @@ -1072,8 +1063,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( return Err(()); } Err(e) => { - debug!("assemble_candidates_from_impls: selection error {:?}", - e); + debug!("assemble_candidates_from_impls: selection error {:?}", e); candidate_set.mark_error(e); return Err(()); } @@ -1295,11 +1285,11 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( let mut env_predicates = env_predicates.filter(|data| { let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - selcx.infcx().probe(|_| { + selcx.infcx().probe(|_| selcx.infcx().at(&obligation.cause, obligation.param_env) .sup(obligation_poly_trait_ref, data_poly_trait_ref) .is_ok() - }) + ) }); // select the first matching one; there really ought to be one or @@ -1447,7 +1437,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( obligation.predicate.self_ty(), fn_sig, flag) - .map_bound(|(trait_ref, ret_type)| { + .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { projection_ty: ty::ProjectionTy::from_ref_and_name( tcx, @@ -1456,7 +1446,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( ), ty: ret_type } - }); + ); confirm_param_env_candidate(selcx, obligation, predicate) } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index fd8898dffd4..f5fb183ec1a 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -57,22 +57,19 @@ pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>> { debug!("c_ty = {:?}", c_ty); match &gcx.dropck_outlives(c_ty) { Ok(result) if result.is_proven() => { - match self.infcx.instantiate_query_result_and_region_obligations( + if let Ok(InferOk { value, obligations }) = + self.infcx.instantiate_query_result_and_region_obligations( self.cause, self.param_env, &orig_values, - result, - ) { - Ok(InferOk { value, obligations }) => { - let ty = self.infcx.resolve_type_vars_if_possible(&ty); - let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); - return InferOk { - value: kinds, - obligations, - }; - } - - Err(_) => { /* fallthrough to error-handling code below */ } + result) + { + let ty = self.infcx.resolve_type_vars_if_possible(&ty); + let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); + return InferOk { + value: kinds, + obligations, + }; } } @@ -161,12 +158,7 @@ impl<'tcx> FromIterator> for DtorckConstraint<'tcx> { fn from_iter>>(iter: I) -> Self { let mut result = Self::empty(); - for DtorckConstraint { - outlives, - dtorck_types, - overflows, - } in iter - { + for DtorckConstraint { outlives, dtorck_types, overflows } in iter { result.outlives.extend(outlives); result.dtorck_types.extend(dtorck_types); result.overflows.extend(overflows); @@ -254,7 +246,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> } } - // The following *might* require a destructor: it would deeper inspection to tell. + // The following *might* require a destructor: needs deeper inspection. ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index ea8bc3b20aa..9b9643aab97 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -48,6 +48,13 @@ pub fn normalize(&self, value: &T) -> Result, NoSolution> value, self.param_env, ); + if !value.has_projections() { + return Ok(Normalized { + value: value.clone(), + obligations: vec![], + }); + } + let mut normalizer = QueryNormalizer { infcx: self.infcx, cause: self.cause, @@ -56,12 +63,6 @@ pub fn normalize(&self, value: &T) -> Result, NoSolution> error: false, anon_depth: 0, }; - if !value.has_projections() { - return Ok(Normalized { - value: value.clone(), - obligations: vec![], - }); - } let value1 = value.fold_with(&mut normalizer); if normalizer.error { @@ -154,8 +155,8 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { let gcx = self.infcx.tcx.global_tcx(); let mut orig_values = SmallVec::new(); - let c_data = self.infcx - .canonicalize_query(&self.param_env.and(*data), &mut orig_values); + let c_data = self.infcx.canonicalize_query( + &self.param_env.and(*data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); match gcx.normalize_projection_ty(c_data) { @@ -170,12 +171,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { self.cause, self.param_env, &orig_values, - &result, - ) { - Ok(InferOk { - value: result, - obligations, - }) => { + &result) + { + Ok(InferOk { value: result, obligations }) => { debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); @@ -212,12 +210,9 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc instance, promoted: None, }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => { - let evaluated = evaluated.subst(self.tcx(), substs); - return self.fold_const(evaluated); - } - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + let evaluated = evaluated.subst(self.tcx(), substs); + return self.fold_const(evaluated); } } } else { @@ -228,9 +223,8 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc instance, promoted: None, }; - match tcx.const_eval(param_env.and(cid)) { - Ok(evaluated) => return self.fold_const(evaluated), - Err(_) => {} + if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { + return self.fold_const(evaluated) } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 232ef108537..c6099e15f8b 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -44,8 +44,8 @@ use middle::lang_items; use mir::interpret::{GlobalId}; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::sync::Lock; -use rustc_data_structures::bitvec::BitArray; use std::iter; use std::cmp; use std::fmt; @@ -55,7 +55,6 @@ use hir; use util::nodemap::{FxHashMap, FxHashSet}; - pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, @@ -149,7 +148,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { #[derive(Clone)] pub struct SelectionCache<'tcx> { hashmap: Lock, - WithDepNode>>>>, + WithDepNode>>>>, } /// The selection process begins by considering all impls, where @@ -623,9 +622,9 @@ pub fn evaluate_obligation_recursively(&mut self, obligation: &PredicateObligation<'tcx>) -> Result { - self.probe(|this, _| { + self.probe(|this, _| this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - }) + ) } /// Evaluates the predicates in `predicates` recursively. Note that @@ -717,13 +716,9 @@ fn evaluate_predicate_recursively<'o>(&mut self, self.infcx.projection_cache.borrow_mut().complete(key); } result - } - Ok(None) => { - Ok(EvaluatedToAmbig) - } - Err(_) => { - Ok(EvaluatedToErr) - } + }, + Ok(None) => Ok(EvaluatedToAmbig), + Err(_) => Ok(EvaluatedToErr) } } @@ -735,10 +730,8 @@ fn evaluate_predicate_recursively<'o>(&mut self, } else { Ok(EvaluatedToErr) } - } - None => { - Ok(EvaluatedToAmbig) - } + }, + None => Ok(EvaluatedToAmbig) } } @@ -901,13 +894,13 @@ fn evaluate_stack<'o>(&mut self, // same unbound type variable. if let Some(rec_index) = stack.iter() - .skip(1) // skip top-most frame - .position(|prev| stack.obligation.param_env == prev.obligation.param_env && - stack.fresh_trait_ref == prev.fresh_trait_ref) + .skip(1) // skip top-most frame + .position(|prev| stack.obligation.param_env == prev.obligation.param_env && + stack.fresh_trait_ref == prev.fresh_trait_ref) { debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); - let cycle = stack.iter().skip(1).take(rec_index+1); + let cycle = stack.iter().skip(1).take(rec_index + 1); let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); if self.coinductive_match(cycle) { debug!("evaluate_stack({:?}) --> recursive, coinductive", @@ -947,10 +940,8 @@ fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool { let result = match predicate { ty::Predicate::Trait(ref data) => { self.tcx().trait_is_auto(data.def_id()) - } - _ => { - false - } + }, + _ => false }; debug!("coinductive_predicate({:?}) = {:?}", predicate, result); result @@ -1088,9 +1079,9 @@ fn candidate_from_obligation<'o>(&mut self, } // If no match, compute result and insert into cache. - let (candidate, dep_node) = self.in_task(|this| { + let (candidate, dep_node) = self.in_task(|this| this.candidate_from_obligation_no_cache(stack) - }); + ); debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate); @@ -1104,9 +1095,9 @@ fn candidate_from_obligation<'o>(&mut self, fn in_task(&mut self, op: OP) -> (R, DepNodeIndex) where OP: FnOnce(&mut Self) -> R { - let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || { + let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self) - }); + ); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } @@ -1138,46 +1129,53 @@ fn candidate_from_obligation_no_cache<'o>(&mut self, return Ok(None); } - match self.is_knowable(stack) { - None => {} - Some(conflict) => { - debug!("coherence stage: not knowable"); - if self.intercrate_ambiguity_causes.is_some() { - debug!("evaluate_stack: intercrate_ambiguity_causes is some"); - // Heuristics: show the diagnostics when there are no candidates in crate. - if let Ok(candidate_set) = self.assemble_candidates(stack) { - let no_candidates_apply = - candidate_set - .vec - .iter() - .map(|c| self.evaluate_candidate(stack, &c)) - .collect::, OverflowError>>()? - .iter() - .all(|r| !r.may_apply()); - if !candidate_set.ambiguous && no_candidates_apply { - let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let trait_desc = trait_ref.to_string(); - let self_desc = if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }; - let cause = if let Conflict::Upstream = conflict { - IntercrateAmbiguityCause::UpstreamCrateUpdate { - trait_desc, - self_desc, - } - } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } - }; - debug!("evaluate_stack: pushing cause = {:?}", cause); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + if let Some(conflict) = self.is_knowable(stack) { + debug!("coherence stage: not knowable"); + if self.intercrate_ambiguity_causes.is_some() { + debug!("evaluate_stack: intercrate_ambiguity_causes is some"); + // Heuristics: show the diagnostics when there are no candidates in crate. + if let Ok(candidate_set) = self.assemble_candidates(stack) { + let mut no_candidates_apply = true; + { + let evaluated_candidates = candidate_set.vec.iter().map(|c| + self.evaluate_candidate(stack, &c)); + + for ec in evaluated_candidates { + match ec { + Ok(c) => { + if c.may_apply() { + no_candidates_apply = false; + break + } + }, + Err(e) => return Err(e.into()) + } } } + + if !candidate_set.ambiguous && no_candidates_apply { + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let trait_desc = trait_ref.to_string(); + let self_desc = if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }; + let cause = if let Conflict::Upstream = conflict { + IntercrateAmbiguityCause::UpstreamCrateUpdate { + trait_desc, + self_desc, + } + } else { + IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } + }; + debug!("evaluate_stack: pushing cause = {:?}", cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + } } - return Ok(None); } + return Ok(None); } let candidate_set = self.assemble_candidates(stack)?; @@ -1434,9 +1432,9 @@ fn assemble_candidates<'o>(&mut self, // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. - let def_id = obligation.predicate.def_id(); let lang_items = self.tcx().lang_items(); + if lang_items.copy_trait() == Some(def_id) { debug!("obligation self ty is {:?}", obligation.predicate.skip_binder().self_ty()); @@ -1495,15 +1493,15 @@ fn assemble_candidates_from_projected_tys(&mut self, ty::Projection(_) | ty::Opaque(..) => {} ty::Infer(ty::TyVar(_)) => { span_bug!(obligation.cause.span, - "Self=_ should have been handled by assemble_candidates"); + "Self=_ should have been handled by assemble_candidates"); } _ => return } - let result = self.probe(|this, snapshot| { + let result = self.probe(|this, snapshot| this.match_projection_obligation_against_definition_bounds(obligation, snapshot) - }); + ); if result { candidates.vec.push(ProjectionCandidate); @@ -1533,7 +1531,7 @@ fn match_projection_obligation_against_definition_bounds( span_bug!( obligation.cause.span, "match_projection_obligation_against_definition_bounds() called \ - but self-ty not a projection: {:?}", + but self-ty is not a projection: {:?}", skol_trait_predicate.trait_ref.self_ty()); } }; @@ -1637,14 +1635,14 @@ fn evaluate_where_clause<'o>(&mut self, where_clause_trait_ref: ty::PolyTraitRef<'tcx>) -> Result { - self.probe(move |this, _| { + self.probe(move |this, _| match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { this.evaluate_predicates_recursively(stack.list(), obligations.iter()) } Err(()) => Ok(EvaluatedToErr) } - }) + ) } fn assemble_generator_candidates(&mut self, @@ -1667,15 +1665,15 @@ fn assemble_generator_candidates(&mut self, obligation); candidates.vec.push(GeneratorCandidate); - Ok(()) } ty::Infer(ty::TyVar(_)) => { debug!("assemble_generator_candidates: ambiguous self-type"); candidates.ambiguous = true; - return Ok(()); } - _ => { return Ok(()); } + _ => {} } + + Ok(()) } /// Check for the artificial impl that the compiler will create for an obligation like `X : @@ -1712,16 +1710,16 @@ fn assemble_closure_candidates(&mut self, debug!("assemble_unboxed_candidates: closure_kind not yet known"); candidates.vec.push(ClosureCandidate); } - }; - Ok(()) + } } ty::Infer(ty::TyVar(_)) => { debug!("assemble_unboxed_closure_candidates: ambiguous self-type"); candidates.ambiguous = true; - return Ok(()); } - _ => { return Ok(()); } + _ => {} } + + Ok(()) } /// Implement one of the `Fn()` family for a fn pointer. @@ -1742,7 +1740,6 @@ fn assemble_fn_pointer_candidates(&mut self, debug!("assemble_fn_pointer_candidates: ambiguous self-type"); candidates.ambiguous = true; // could wind up being a fn() type } - // provide an impl, but only for suitable `fn` pointers ty::FnDef(..) | ty::FnPtr(_) => { if let ty::FnSig { @@ -1754,8 +1751,7 @@ fn assemble_fn_pointer_candidates(&mut self, candidates.vec.push(FnPointerCandidate); } } - - _ => { } + _ => {} } Ok(()) @@ -1773,18 +1769,15 @@ fn assemble_candidates_from_impls(&mut self, obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.probe(|this, snapshot| { /* [1] */ - match this.match_impl(impl_def_id, obligation, snapshot) { - Ok(skol_map) => { - candidates.vec.push(ImplCandidate(impl_def_id)); - - // NB: we can safely drop the skol map - // since we are in a probe [1] - mem::drop(skol_map); - } - Err(_) => { } + self.probe(|this, snapshot| /* [1] */ + if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) { + candidates.vec.push(ImplCandidate(impl_def_id)); + + // NB: we can safely drop the skol map + // since we are in a probe [1] + mem::drop(skol_map); } - }); + ); } ); @@ -1874,7 +1867,7 @@ fn assemble_candidates_from_object_ty(&mut self, ty::Dynamic(ref data, ..) => { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ - pushing candidate"); + pushing candidate"); candidates.vec.push(BuiltinObjectCandidate); return; } @@ -1889,9 +1882,7 @@ fn assemble_candidates_from_object_ty(&mut self, candidates.ambiguous = true; // could wind up being an object type return; } - _ => { - return; - } + _ => return }; debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", @@ -1904,12 +1895,12 @@ fn assemble_candidates_from_object_ty(&mut self, // but `Foo` is declared as `trait Foo : Bar`. let upcast_trait_refs = util::supertraits(this.tcx(), poly_trait_ref) - .filter(|upcast_trait_ref| { + .filter(|upcast_trait_ref| this.probe(|this, _| { let upcast_trait_ref = upcast_trait_ref.clone(); this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() }) - }) + ) .count(); if upcast_trait_refs > 1 { @@ -2028,6 +2019,10 @@ fn candidate_should_be_dropped_in_favor_of<'o>( other: &EvaluatedCandidate<'tcx>) -> bool { + if victim.candidate == other.candidate { + return true; + } + // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. @@ -2035,10 +2030,6 @@ fn candidate_should_be_dropped_in_favor_of<'o>( cand.is_global() && !cand.has_late_bound_regions() }; - if victim.candidate == other.candidate { - return true; - } - match other.candidate { // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the @@ -2046,9 +2037,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>( BuiltinCandidate { has_nested: false } => true, ParamCandidate(ref cand) => match victim.candidate { AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates"); + bug!("default implementations shouldn't be recorded \ + when there are other valid candidates"); } // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the @@ -2077,9 +2067,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>( ObjectCandidate | ProjectionCandidate => match victim.candidate { AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates"); + bug!("default implementations shouldn't be recorded \ + when there are other valid candidates"); } // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the @@ -2151,7 +2140,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>( fn assemble_builtin_bound_candidates<'o>(&mut self, conditions: BuiltinImplConditions<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(),SelectionError<'tcx>> + -> Result<(), SelectionError<'tcx>> { match conditions { BuiltinImplConditions::Where(nested) => { @@ -2159,18 +2148,20 @@ fn assemble_builtin_bound_candidates<'o>(&mut self, candidates.vec.push(BuiltinCandidate { has_nested: nested.skip_binder().len() > 0 }); - Ok(()) } - BuiltinImplConditions::None => { Ok(()) } + BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { debug!("assemble_builtin_bound_candidates: ambiguous builtin"); - Ok(candidates.ambiguous = true) + candidates.ambiguous = true; } } + + Ok(()) } - fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>) - -> BuiltinImplConditions<'tcx> + fn sized_conditions(&mut self, + obligation: &TraitObligation<'tcx>) + -> BuiltinImplConditions<'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; @@ -2216,8 +2207,9 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>) } } - fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>) - -> BuiltinImplConditions<'tcx> + fn copy_clone_conditions(&mut self, + obligation: &TraitObligation<'tcx>) + -> BuiltinImplConditions<'tcx> { // NOTE: binder moved to (*) let self_ty = self.infcx.shallow_resolve( @@ -2551,17 +2543,15 @@ fn confirm_builtin_candidate(&mut self, let lang_items = self.tcx().lang_items(); let obligations = if has_nested { let trait_def = obligation.predicate.def_id(); - let conditions = match trait_def { - _ if Some(trait_def) == lang_items.sized_trait() => { + let conditions = + if Some(trait_def) == lang_items.sized_trait() { self.sized_conditions(obligation) - } - _ if Some(trait_def) == lang_items.copy_trait() => { + } else if Some(trait_def) == lang_items.copy_trait() { self.copy_clone_conditions(obligation) - } - _ if Some(trait_def) == lang_items.clone_trait() => { + } else if Some(trait_def) == lang_items.clone_trait() { self.copy_clone_conditions(obligation) - } - _ => bug!("unexpected builtin trait {:?}", trait_def) + } else { + bug!("unexpected builtin trait {:?}", trait_def) }; let nested = match conditions { BuiltinImplConditions::Where(nested) => nested, @@ -2608,10 +2598,10 @@ fn confirm_auto_impl_candidate(&mut self, /// See `confirm_auto_impl_candidate` fn vtable_auto_impl(&mut self, - obligation: &TraitObligation<'tcx>, - trait_def_id: DefId, - nested: ty::Binder>>) - -> VtableAutoImplData> + obligation: &TraitObligation<'tcx>, + trait_def_id: DefId, + nested: ty::Binder>>) + -> VtableAutoImplData> { debug!("vtable_auto_impl: nested={:?}", nested); @@ -2731,10 +2721,8 @@ fn confirm_object_candidate(&mut self, ty::Dynamic(ref data, ..) => { data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } - _ => { - span_bug!(obligation.cause.span, - "object candidate with non-object"); - } + _ => span_bug!(obligation.cause.span, + "object candidate with non-object") }; let mut upcast_trait_ref = None; @@ -2752,10 +2740,9 @@ fn confirm_object_candidate(&mut self, // record it for later.) let nonmatching = util::supertraits(tcx, poly_trait_ref) - .take_while(|&t| { - match - self.commit_if_ok( - |this, _| this.match_poly_trait_ref(obligation, t)) + .take_while(|&t| + match self.commit_if_ok(|this, _| + this.match_poly_trait_ref(obligation, t)) { Ok(obligations) => { upcast_trait_ref = Some(t); @@ -2764,16 +2751,13 @@ fn confirm_object_candidate(&mut self, } Err(_) => { true } } - }); + ); // Additionally, for each of the nonmatching predicates that // we pass over, we sum up the set of number of vtable // entries, so that we can compute the offset for the selected // trait. - vtable_base = - nonmatching.map(|t| tcx.count_own_vtable_entries(t)) - .sum(); - + vtable_base = nonmatching.map(|t| tcx.count_own_vtable_entries(t)).sum(); } VtableObjectData { @@ -2816,7 +2800,7 @@ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>) fn confirm_generator_candidate(&mut self, obligation: &TraitObligation<'tcx>) -> Result>, - SelectionError<'tcx>> + SelectionError<'tcx>> { // ok to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope @@ -2869,10 +2853,11 @@ fn confirm_closure_candidate(&mut self, { debug!("confirm_closure_candidate({:?})", obligation); - let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) { - Some(k) => k, - None => bug!("closure candidate for non-fn trait {:?}", obligation) - }; + let kind = self.tcx() + .lang_items() + .fn_trait_kind(obligation.predicate.def_id()) + .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", + obligation)); // ok to skip binder because the substs on closure types never // touch bound regions, they just capture the in-scope @@ -2901,9 +2886,9 @@ fn confirm_closure_candidate(&mut self, obligations.extend( self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref)?); + obligation.param_env, + obligation.predicate.to_poly_trait_ref(), + trait_ref)?); obligations.push(Obligation::new( obligation.cause.clone(), @@ -3008,20 +2993,19 @@ fn confirm_builtin_unsize_candidate(&mut self, (_, &ty::Dynamic(ref data, r)) => { let mut object_dids = data.auto_traits().chain(data.principal().map(|p| p.def_id())); - if let Some(did) = object_dids.find(|did| { - !tcx.is_object_safe(*did) - }) { + if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { return Err(TraitNotObjectSafe(did)) } let cause = ObligationCause::new(obligation.cause.span, obligation.cause.body_id, ObjectCastObligation(target)); - let mut push = |predicate| { - nested.push(Obligation::with_depth(cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - predicate)); + + let predicate_to_obligation = |predicate| { + Obligation::with_depth(cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + predicate) }; // Create obligations: @@ -3030,21 +3014,22 @@ fn confirm_builtin_unsize_candidate(&mut self, // words, if the object type is Foo+Send, this would create an obligation for the // Send check.) // - Projection predicates - for predicate in data.iter() { - push(predicate.with_self_ty(tcx, source)); - } + nested.extend(data.iter().map(|d| + predicate_to_obligation(d.with_self_ty(tcx, source)) + )); // We can only make objects from sized types. let tr = ty::TraitRef { def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem), substs: tcx.mk_substs_trait(source, &[]), }; - push(tr.to_predicate()); + nested.push(predicate_to_obligation(tr.to_predicate())); // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, r); - push(ty::Binder::dummy(outlives).to_predicate()); + nested.push(predicate_to_obligation( + ty::Binder::dummy(outlives).to_predicate())); } // [T; n] -> [T]. @@ -3069,7 +3054,7 @@ fn confirm_builtin_unsize_candidate(&mut self, } else { return Err(Unimplemented); }; - let mut ty_params = BitArray::new(substs_a.types().count()); + let mut ty_params = BitSet::new_empty(substs_a.types().count()); let mut found = false; for ty in field.walk() { if let ty::Param(p) = ty.sty { @@ -3105,13 +3090,13 @@ fn confirm_builtin_unsize_candidate(&mut self, // Check that the source struct with the target's // unsized parameters is equal to the target. - let params = substs_a.iter().enumerate().map(|(i, &k)| { + let params = substs_a.iter().enumerate().map(|(i, &k)| if ty_params.contains(i) { substs_b.type_at(i).into() } else { k } - }); + ); let new_struct = tcx.mk_adt(def, tcx.mk_substs(params)); let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) @@ -3236,10 +3221,9 @@ fn match_impl(&mut self, let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) .eq(skol_obligation_trait_ref, impl_trait_ref) - .map_err(|e| { - debug!("match_impl: failed eq_trait_refs due to `{}`", e); - () - })?; + .map_err(|e| + debug!("match_impl: failed eq_trait_refs due to `{}`", e) + )?; nested_obligations.extend(obligations); if let Err(e) = self.infcx.leak_check(false, @@ -3288,7 +3272,7 @@ fn fast_reject_trait_refs(&mut self, fn match_where_clause_trait_ref(&mut self, obligation: &TraitObligation<'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>,()> + -> Result>, ()> { self.match_poly_trait_ref(obligation, where_clause_trait_ref) } @@ -3298,7 +3282,7 @@ fn match_where_clause_trait_ref(&mut self, fn match_poly_trait_ref(&mut self, obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>,()> + -> Result>, ()> { debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}", obligation, @@ -3350,20 +3334,20 @@ fn closure_trait_ref_unnormalized(&mut self, // in fact unparameterized (or at least does not reference any // regions bound in the obligation). Still probably some // refactoring could make this nicer. - self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), obligation.predicate - .skip_binder().self_ty(), // (1) + .skip_binder() + .self_ty(), // (1) closure_type, util::TupleArgumentsFlag::No) .map_bound(|(trait_ref, _)| trait_ref) } fn generator_trait_ref_unnormalized(&mut self, - obligation: &TraitObligation<'tcx>, - closure_def_id: DefId, - substs: ty::GeneratorSubsts<'tcx>) - -> ty::PolyTraitRef<'tcx> + obligation: &TraitObligation<'tcx>, + closure_def_id: DefId, + substs: ty::GeneratorSubsts<'tcx>) + -> ty::PolyTraitRef<'tcx> { let gen_sig = substs.poly_sig(closure_def_id, self.tcx()); @@ -3375,7 +3359,8 @@ fn generator_trait_ref_unnormalized(&mut self, self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(), obligation.predicate - .skip_binder().self_ty(), // (1) + .skip_binder() + .self_ty(), // (1) gen_sig) .map_bound(|(trait_ref, ..)| trait_ref) } @@ -3453,8 +3438,8 @@ fn impl_or_trait_obligations(&mut self, impl<'tcx> TraitObligation<'tcx> { #[allow(unused_comparisons)] pub fn derived_cause(&self, - variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>) - -> ObligationCause<'tcx> + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>) + -> ObligationCause<'tcx> { /*! * Creates a cause for obligations that are derived from diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 9343eff9e79..dbd84397b59 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -100,10 +100,10 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, } fulfill_implication(infcx, param_env, source_trait_ref, target_impl) - .unwrap_or_else(|_| { + .unwrap_or_else(|_| bug!("When translating substitutions for specialization, the expected \ specialization failed to hold") - }) + ) } specialization_graph::Node::Trait(..) => source_trait_ref.substs, }; @@ -137,17 +137,15 @@ pub fn find_associated_item<'a, 'tcx>( let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, substs, node_item.node); let substs = infcx.tcx.erase_regions(&substs); - tcx.lift(&substs).unwrap_or_else(|| { + tcx.lift(&substs).unwrap_or_else(|| bug!("find_method: translate_substs \ returned {:?} which contains inference types/regions", - substs); - }) + substs) + ) }); (node_item.item.def_id, substs) } - None => { - bug!("{:?} not found in {:?}", item, impl_data.impl_def_id) - } + None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id) } } @@ -312,8 +310,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx -> Lrc { let mut sg = specialization_graph::Graph::new(); - let mut trait_impls = Vec::new(); - tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did)); + let mut trait_impls = tcx.all_impls(trait_id); // The coherence checking implementation seems to rely on impls being // iterated over (roughly) in definition order, so we are sorting by @@ -367,9 +364,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx "first implementation here".to_string()); err.span_label(impl_span, format!("conflicting implementation{}", - overlap.self_desc - .map_or(String::new(), - |ty| format!(" for `{}`", ty)))); + overlap.self_desc + .map_or(String::new(), + |ty| format!(" for `{}`", ty)))); } Err(cname) => { let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { @@ -428,7 +425,9 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option { // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. let predicates = tcx.predicates_of(impl_def_id).predicates; - let mut pretty_predicates = Vec::with_capacity(predicates.len()); + let mut pretty_predicates = Vec::with_capacity( + predicates.len() + types_without_default_bounds.len()); + for p in predicates { if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { if Some(poly_trait_ref.def_id()) == sized_trait { @@ -438,9 +437,11 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option { } pretty_predicates.push(p.to_string()); } + pretty_predicates.extend( types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)) ); + if !pretty_predicates.is_empty() { write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap(); } diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a7652574c1a..756f55545bc 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -390,11 +390,12 @@ fn next(&mut self) -> Option { let cur = self.current_source.take(); if let Some(Node::Impl(cur_impl)) = cur { let parent = self.specialization_graph.parent(cur_impl); - if parent == self.trait_def_id { - self.current_source = Some(Node::Trait(parent)); + + self.current_source = if parent == self.trait_def_id { + Some(Node::Trait(parent)) } else { - self.current_source = Some(Node::Impl(parent)); - } + Some(Node::Impl(parent)) + }; } cur } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 10e930d1c92..a4230707b70 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -166,10 +166,10 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option Some(super::Unimplemented), super::OutputTypeParameterMismatch(a, b, ref err) => { - tcx.lift(&(a, b)).and_then(|(a, b)| { + tcx.lift(&(a, b)).and_then(|(a, b)| tcx.lift(err) .map(|err| super::OutputTypeParameterMismatch(a, b, err)) - }) + ) } super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)), super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure( @@ -193,10 +193,10 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { tcx.lift(&ty).map(super::ReferenceOutlivesReferent) } - super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| { + super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| tcx.lift(&r) - .and_then(|r| Some(super::ObjectTypeBound(ty, r))) - }), + .and_then(|r| Some(super::ObjectTypeBound(ty, r))) + ), super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation), super::AssignmentLhsSized => Some(super::AssignmentLhsSized), super::TupleInitializerSized => Some(super::TupleInitializerSized), @@ -245,13 +245,13 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option Lift<'tcx> for traits::DerivedObligationCause<'a> { type Lifted = traits::DerivedObligationCause<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| { + tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| tcx.lift(&*self.parent_code) - .map(|code| traits::DerivedObligationCause { - parent_trait_ref: trait_ref, - parent_code: Rc::new(code), - }) - }) + .map(|code| traits::DerivedObligationCause { + parent_trait_ref: trait_ref, + parent_code: Rc::new(code), + }) + ) } } @@ -275,40 +275,40 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option tcx.lift(&substs).map(|substs| { + }) => tcx.lift(&substs).map(|substs| traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested, }) - }), + ), traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)), traits::VtableGenerator(traits::VtableGeneratorData { generator_def_id, substs, nested, - }) => tcx.lift(&substs).map(|substs| { + }) => tcx.lift(&substs).map(|substs| traits::VtableGenerator(traits::VtableGeneratorData { generator_def_id: generator_def_id, substs: substs, nested: nested, }) - }), + ), traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested, - }) => tcx.lift(&substs).map(|substs| { + }) => tcx.lift(&substs).map(|substs| traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested, }) - }), + ), traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => { - tcx.lift(&fn_ty).map(|fn_ty| { + tcx.lift(&fn_ty).map(|fn_ty| traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) - }) + ) } traits::VtableParam(n) => Some(traits::VtableParam(n)), traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)), @@ -316,13 +316,13 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option tcx.lift(&upcast_trait_ref).map(|trait_ref| { + }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| traits::VtableObject(traits::VtableObjectData { upcast_trait_ref: trait_ref, vtable_base, nested, }) - }), + ), } } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 40f13ac06f5..2ca8214daf7 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -346,8 +346,7 @@ fn next(&mut self) -> Option> { Some(ty::Predicate::Trait(data)) => { return Some(data.to_poly_trait_ref()); } - Some(_) => { - } + Some(_) => {} } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d1f37250379..b7b0fdca2e6 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -17,7 +17,7 @@ use session::config::{BorrowckMode, OutputFilenames}; use session::config::CrateType; use middle; -use hir::{TraitCandidate, HirId, ItemLocalId}; +use hir::{TraitCandidate, HirId, ItemLocalId, Node}; use hir::def::{Def, Export}; use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use hir::map as hir_map; @@ -872,6 +872,18 @@ fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { } } +// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime +// conflict. +#[derive(Debug)] +pub struct FreeRegionInfo { + // def id corresponding to FreeRegion + pub def_id: DefId, + // the bound region corresponding to FreeRegion + pub boundregion: ty::BoundRegion, + // checks if bound region is in Impl Item + pub is_impl_item: bool, +} + /// The central data structure of the compiler. It stores references /// to the various **arenas** and also houses the results of the /// various **compiler queries** that have been performed. See the @@ -1247,7 +1259,11 @@ pub fn create_and_enter(s: &'tcx Session, .collect(), hir, def_path_hash_to_def_id, - queries: query::Queries::new(providers, on_disk_query_result_cache), + queries: query::Queries::new( + providers, + extern_providers, + on_disk_query_result_cache, + ), rcache: Lock::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), @@ -1432,10 +1448,37 @@ pub fn serialize_query_result_cache(self, self.queries.on_disk_cache.serialize(self.global_tcx(), encoder) } + /// This checks whether one is allowed to have pattern bindings + /// that bind-by-move on a match arm that has a guard, e.g.: + /// + /// ```rust + /// match foo { A(inner) if { /* something */ } => ..., ... } + /// ``` + /// + /// It is separate from check_for_mutation_in_guard_via_ast_walk, + /// because that method has a narrower effect that can be toggled + /// off via a separate `-Z` flag, at least for the short term. + pub fn allow_bind_by_move_patterns_with_guards(self) -> bool { + self.features().bind_by_move_pattern_guards && self.use_mir_borrowck() + } + /// If true, we should use a naive AST walk to determine if match /// guard could perform bad mutations (or mutable-borrows). pub fn check_for_mutation_in_guard_via_ast_walk(self) -> bool { - !self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard + // If someone passes the `-Z` flag, they're asking for the footgun. + if self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard { + return false; + } + + // If someone requests the feature, then be a little more + // careful and ensure that MIR-borrowck is enabled (which can + // happen via edition selection, via `feature(nll)`, or via an + // appropriate `-Z` flag) before disabling the mutation check. + if self.allow_bind_by_move_patterns_with_guards() { + return false; + } + + return true; } /// If true, we should use the AST-based borrowck (we may *also* use @@ -1567,6 +1610,74 @@ pub fn local_crate_exports_generics(self) -> bool { } }) } + + // This method returns the DefId and the BoundRegion corresponding to the given region. + pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option { + let (suitable_region_binding_scope, bound_region) = match *region { + ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), + ty::ReEarlyBound(ref ebr) => ( + self.parent_def_id(ebr.def_id).unwrap(), + ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), + ), + _ => return None, // not a free region + }; + + let node_id = self.hir + .as_local_node_id(suitable_region_binding_scope) + .unwrap(); + let is_impl_item = match self.hir.find(node_id) { + Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false, + Some(Node::ImplItem(..)) => { + self.is_bound_region_in_impl_item(suitable_region_binding_scope) + } + _ => return None, + }; + + return Some(FreeRegionInfo { + def_id: suitable_region_binding_scope, + boundregion: bound_region, + is_impl_item: is_impl_item, + }); + } + + pub fn return_type_impl_trait( + &self, + scope_def_id: DefId, + ) -> Option> { + let ret_ty = self.type_of(scope_def_id); + match ret_ty.sty { + ty::FnDef(_, _) => { + let sig = ret_ty.fn_sig(*self); + let output = self.erase_late_bound_regions(&sig.output()); + if output.is_impl_trait() { + Some(output) + } else { + None + } + } + _ => None + } + } + + // Here we check if the bound region is in Impl Item. + pub fn is_bound_region_in_impl_item( + &self, + suitable_region_binding_scope: DefId, + ) -> bool { + let container_id = self.associated_item(suitable_region_binding_scope) + .container + .id(); + if self.impl_trait_ref(container_id).is_some() { + // For now, we do not try to target impls of traits. This is + // because this message is going to suggest that the user + // change the fn signature, but they may not be free to do so, + // since the signature must match the trait. + // + // FIXME(#42706) -- in some cases, we could do better here. + return true; + } + false + } } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d9e3bdaf266..940da6099e0 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -80,7 +80,7 @@ pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; -pub use self::context::{TyCtxt, GlobalArenas, AllArenas, tls, keep_local}; +pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local}; pub use self::context::{Lift, TypeckTables}; pub use self::instance::{Instance, InstanceDef}; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index f0ca168e9e4..79c7e517273 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -49,14 +49,14 @@ use util::common::{ErrorReported}; use util::profiling::ProfileCategory::*; -use rustc_data_structures::indexed_set::IdxSet; -use rustc_target::spec::PanicStrategy; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::StableVec; +use rustc_data_structures::sync::Lrc; +use rustc_target::spec::PanicStrategy; use std::ops::Deref; -use rustc_data_structures::sync::Lrc; use std::sync::Arc; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::symbol::InternedString; @@ -208,7 +208,7 @@ /// Maps DefId's that have an associated Mir to the result /// of the MIR qualify_consts pass. The actual meaning of /// the value isn't known except to the pass itself. - [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc>), + [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc>), /// Fetch the MIR for a given def-id right after it's built - this includes /// unreachable code. diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 3c26732fbac..25e72f462e6 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -692,10 +692,12 @@ macro_rules! define_queries_inner { impl<$tcx> Queries<$tcx> { pub fn new( providers: IndexVec>, + fallback_extern_providers: Providers<$tcx>, on_disk_cache: OnDiskCache<'tcx>, ) -> Self { Queries { providers, + fallback_extern_providers: Box::new(fallback_extern_providers), on_disk_cache, $($name: Lock::new(QueryCache::new())),* } @@ -818,7 +820,13 @@ fn to_dep_node(tcx: TyCtxt<'_, $tcx, '_>, key: &Self::Key) -> DepNode { #[inline] fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value { __query_compute::$name(move || { - let provider = tcx.queries.providers[key.query_crate()].$name; + let provider = tcx.queries.providers.get(key.query_crate()) + // HACK(eddyb) it's possible crates may be loaded after + // the query engine is created, and because crate loading + // is not yet integrated with the query engine, such crates + // would be be missing appropriate entries in `providers`. + .unwrap_or(&tcx.queries.fallback_extern_providers) + .$name; provider(tcx.global_tcx(), key) }) } @@ -899,6 +907,7 @@ pub(crate) struct Queries<$tcx> { pub(crate) on_disk_cache: OnDiskCache<'tcx>, providers: IndexVec>, + fallback_extern_providers: Box>, $($(#[$attr])* $name: Lock>>,)* } diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 6332080a183..fd3f7a12376 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -138,6 +138,15 @@ pub fn for_each_relevant_impl(self, } } } + + /// Return a vector containing all impls + pub fn all_impls(self, def_id: DefId) -> Vec { + let impls = self.trait_impls_of(def_id); + + impls.blanket_impls.iter().chain( + impls.non_blanket_impls.values().flatten() + ).cloned().collect() + } } // Query provider for `trait_impls_of`. diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 5ffb77dda68..9a1add26bb0 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -769,7 +769,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", br) } ty::ReScope(scope) if cx.identify_regions => { - match scope.data() { + match scope.data { region::ScopeData::Node => write!(f, "'{}s", scope.item_local_id().as_usize()), region::ScopeData::CallSite => diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 1af117c97f5..40bfbf1596a 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -767,8 +767,12 @@ pub fn analyze_restrictions_on_use(&self, let mut ret = UseOk; + let scope = region::Scope { + id: expr_id, + data: region::ScopeData::Node + }; self.each_in_scope_loan_affecting_path( - region::Scope::Node(expr_id), use_path, |loan| { + scope, use_path, |loan| { if !compatible_borrow_kinds(loan.kind, borrow_kind) { ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span); false @@ -886,7 +890,10 @@ fn check_assignment(&self, // Check that we don't invalidate any outstanding loans if let Some(loan_path) = opt_loan_path(assignee_cmt) { - let scope = region::Scope::Node(assignment_id); + let scope = region::Scope { + id: assignment_id, + data: region::ScopeData::Node + }; self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.report_illegal_mutation(assignment_span, &loan_path, loan); false diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 6c83e2dd1c2..dc400c6ef3e 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -43,7 +43,10 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let mut glcx = GatherLoanCtxt { bccx, all_loans: Vec::new(), - item_ub: region::Scope::Node(bccx.tcx.hir.body(body).value.hir_id.local_id), + item_ub: region::Scope { + id: bccx.tcx.hir.body(body).value.hir_id.local_id, + data: region::ScopeData::Node + }, move_data: MoveData::default(), move_error_collector: move_error::MoveErrorCollector::new(), }; @@ -375,7 +378,10 @@ fn guarantee_valid(&mut self, }; debug!("loan_scope = {:?}", loan_scope); - let borrow_scope = region::Scope::Node(borrow_id); + let borrow_scope = region::Scope { + id: borrow_id, + data: region::ScopeData::Node + }; let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope); debug!("gen_scope = {:?}", gen_scope); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index ad45c5429a5..fb8744e4d96 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -45,7 +45,7 @@ use std::hash::{Hash, Hasher}; use syntax::ast; use syntax_pos::{MultiSpan, Span}; -use errors::{DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir; use rustc::hir::intravisit::{self, Visitor}; @@ -441,7 +441,7 @@ pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::Scope { LpUpvar(upvar_id) => { let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx); let hir_id = bccx.tcx.hir.node_to_hir_id(block_id); - region::Scope::Node(hir_id.local_id) + region::Scope { id: hir_id.local_id, data: region::ScopeData::Node } } LpDowncast(ref base, _) | LpExtend(ref base, ..) => base.kill_scope(bccx), @@ -867,10 +867,20 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) { }) = cmt.cat { db.note(fn_closure_msg); } else { - db.span_suggestion(sp, msg, suggestion); + db.span_suggestion_with_applicability( + sp, + msg, + suggestion, + Applicability::Unspecified, + ); } } else { - db.span_suggestion(sp, msg, suggestion); + db.span_suggestion_with_applicability( + sp, + msg, + suggestion, + Applicability::Unspecified, + ); } } _ => { @@ -1236,10 +1246,16 @@ fn note_immutability_blame(&self, let let_span = self.tcx.hir.span(node_id); let suggestion = suggest_ref_mut(self.tcx, let_span); if let Some(replace_str) = suggestion { - db.span_suggestion( + db.span_suggestion_with_applicability( let_span, "use a mutable reference instead", replace_str, + // I believe this can be machine applicable, + // but if there are multiple attempted uses of an immutable + // reference, I don't know how rustfix handles it, it might + // attempt fixing them multiple times. + // @estebank + Applicability::Unspecified, ); } } @@ -1292,16 +1308,19 @@ fn note_immutable_local(&self, )) = ty.map(|t| &t.node) { let borrow_expr_id = self.tcx.hir.get_parent_node(borrowed_node_id); - db.span_suggestion( + db.span_suggestion_with_applicability( self.tcx.hir.span(borrow_expr_id), "consider removing the `&mut`, as it is an \ immutable binding to a mutable reference", - snippet + snippet, + Applicability::MachineApplicable, ); } else { - db.span_label( + db.span_suggestion_with_applicability( let_span, - format!("consider changing this to `mut {}`", snippet), + "make this binding mutable", + format!("mut {}", snippet), + Applicability::MachineApplicable, ); } } @@ -1324,12 +1343,15 @@ fn report_out_of_scope_escaping_closure_capture(&self, &cmt_path_or_string, capture_span, Origin::Ast) - .span_suggestion(err.span, - &format!("to force the closure to take ownership of {} \ - (and any other referenced variables), \ - use the `move` keyword", - cmt_path_or_string), - suggestion) + .span_suggestion_with_applicability( + err.span, + &format!("to force the closure to take ownership of {} \ + (and any other referenced variables), \ + use the `move` keyword", + cmt_path_or_string), + suggestion, + Applicability::MachineApplicable, + ) .emit(); self.signal_error(); } diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index 95be2d82123..c03180c02fe 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -1071,6 +1071,10 @@ fn finalize(&mut self) -> Command { // Make the default table accessible self.cmd.arg("--export-table"); + // Rust code should never have warnings, and warnings are often + // indicative of bugs, let's prevent them. + self.cmd.arg("--fatal-warnings"); + let mut cmd = Command::new(""); ::std::mem::swap(&mut cmd, &mut self.cmd); cmd diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index a76f1d50fa7..0484837a48d 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -21,7 +21,7 @@ use syntax_pos::Pos; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use syntax_pos::BytePos; @@ -64,7 +64,7 @@ pub fn create_mir_scopes( }; // Find all the scopes with variables defined in them. - let mut has_variables = BitArray::new(mir.source_scopes.len()); + let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); for var in mir.vars_iter() { let decl = &mir.local_decls[var]; has_variables.insert(decl.visibility_scope); @@ -81,7 +81,7 @@ pub fn create_mir_scopes( fn make_mir_scope(cx: &CodegenCx<'ll, '_>, mir: &Mir, - has_variables: &BitArray, + has_variables: &BitSet, debug_context: &FunctionDebugContextData<'ll>, scope: SourceScope, scopes: &mut IndexVec>) { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0221cfd9b2c..706568b5446 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1803,13 +1803,7 @@ pub fn create_vtable_metadata( llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx), NO_SCOPE_METADATA, name.as_ptr(), - // LLVM 3.9 - // doesn't accept - // null here, so - // pass the name - // as the linkage - // name. - name.as_ptr(), + ptr::null(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, vtable_type, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 6c2601bf1ef..a5f4137c62b 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -8,16 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' -// once support for LLVM 3.9 is dropped. -// -// This method was changed in this LLVM patch: -// https://reviews.llvm.org/D26769 - use super::debuginfo::{ DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, - DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, + DIGlobalVariableExpression, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, DINameSpace, DIFlags, }; @@ -447,7 +441,7 @@ pub mod debuginfo { pub type DIDerivedType = DIType; pub type DICompositeType = DIDerivedType; pub type DIVariable = DIDescriptor; - pub type DIGlobalVariable = DIDescriptor; + pub type DIGlobalVariableExpression = DIDescriptor; pub type DIArray = DIDescriptor; pub type DISubrange = DIDescriptor; pub type DIEnumerator = DIDescriptor; @@ -1330,7 +1324,7 @@ pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: &DIBuilder<'a>, Val: &'a Value, Decl: Option<&'a DIDescriptor>, AlignInBits: u32) - -> &'a DIGlobalVariable; + -> &'a DIGlobalVariableExpression; pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>, Tag: c_uint, diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index 0206744eb2b..c3e3785a724 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -11,7 +11,7 @@ //! An analysis to determine which locals require allocas and //! which do not. -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; @@ -22,7 +22,7 @@ use type_of::LayoutLlvmExt; use super::FunctionCx; -pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray { +pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitSet { let mir = fx.mir; let mut analyzer = LocalAnalyzer::new(fx); @@ -54,7 +54,7 @@ pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray { struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> { fx: &'mir FunctionCx<'a, 'll, 'tcx>, dominators: Dominators, - non_ssa_locals: BitArray, + non_ssa_locals: BitSet, // The location of the first visited direct assignment to each // local, or an invalid location (out of bounds `block` index). first_assignment: IndexVec @@ -67,7 +67,7 @@ fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self { let mut analyzer = LocalAnalyzer { fx, dominators: fx.mir.dominators(), - non_ssa_locals: BitArray::new(fx.mir.local_decls.len()), + non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls) }; diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index 258fe643c30..c61a326e7c8 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -31,7 +31,7 @@ use std::iter; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::IndexVec; pub use self::constant::codegen_static_initializer; @@ -341,7 +341,7 @@ pub fn codegen_mir( debuginfo::start_emitting_source_locations(&fx.debug_context); let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitArray::new(mir.basic_blocks().len()); + let mut visited = BitSet::new_empty(mir.basic_blocks().len()); // Codegen the body of each block using reverse postorder for (bb, _) in rpo { @@ -435,7 +435,7 @@ fn arg_local_refs( bx: &Builder<'a, 'll, 'tcx>, fx: &FunctionCx<'a, 'll, 'tcx>, scopes: &IndexVec>, - memory_locals: &BitArray, + memory_locals: &BitSet, ) -> Vec> { let mir = fx.mir; let tcx = bx.tcx(); diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs deleted file mode 100644 index 45fb5657061..00000000000 --- a/src/librustc_data_structures/array_vec.rs +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A stack-allocated vector, allowing storage of N elements on the stack. - -use std::marker::Unsize; -use std::iter::Extend; -use std::ptr::{self, drop_in_place, NonNull}; -use std::ops::{Deref, DerefMut, Range}; -use std::hash::{Hash, Hasher}; -use std::slice; -use std::fmt; -use std::mem; -use std::mem::ManuallyDrop; -use std::ops::Bound::{Excluded, Included, Unbounded}; -use std::ops::RangeBounds; - -pub unsafe trait Array { - type Element; - type PartialStorage: Unsize<[ManuallyDrop]>; - const LEN: usize; -} - -unsafe impl Array for [T; 1] { - type Element = T; - type PartialStorage = [ManuallyDrop; 1]; - const LEN: usize = 1; -} - -unsafe impl Array for [T; 8] { - type Element = T; - type PartialStorage = [ManuallyDrop; 8]; - const LEN: usize = 8; -} - -unsafe impl Array for [T; 32] { - type Element = T; - type PartialStorage = [ManuallyDrop; 32]; - const LEN: usize = 32; -} - -pub struct ArrayVec { - count: usize, - values: A::PartialStorage -} - -impl Hash for ArrayVec - where A: Array, - A::Element: Hash { - fn hash(&self, state: &mut H) where H: Hasher { - (&self[..]).hash(state); - } -} - -impl Clone for ArrayVec - where A: Array, - A::Element: Clone { - fn clone(&self) -> Self { - let mut v = ArrayVec::new(); - v.extend(self.iter().cloned()); - v - } -} - -impl ArrayVec { - pub fn new() -> Self { - ArrayVec { - count: 0, - values: unsafe { ::std::mem::uninitialized() }, - } - } - - pub fn len(&self) -> usize { - self.count - } - - pub unsafe fn set_len(&mut self, len: usize) { - self.count = len; - } - - /// Panics when the stack vector is full. - pub fn push(&mut self, el: A::Element) { - let arr = &mut self.values as &mut [ManuallyDrop<_>]; - arr[self.count] = ManuallyDrop::new(el); - self.count += 1; - } - - pub fn pop(&mut self) -> Option { - if self.count > 0 { - let arr = &mut self.values as &mut [ManuallyDrop<_>]; - self.count -= 1; - unsafe { - let value = ptr::read(&*arr[self.count]); - Some(value) - } - } else { - None - } - } - - pub fn drain(&mut self, range: R) -> Drain - where R: RangeBounds - { - // Memory safety - // - // When the Drain is first created, it shortens the length of - // the source vector to make sure no uninitialized or moved-from elements - // are accessible at all if the Drain's destructor never gets to run. - // - // Drain will ptr::read out the values to remove. - // When finished, remaining tail of the vec is copied back to cover - // the hole, and the vector length is restored to the new length. - // - let len = self.len(); - let start = match range.start_bound() { - Included(&n) => n, - Excluded(&n) => n + 1, - Unbounded => 0, - }; - let end = match range.end_bound() { - Included(&n) => n + 1, - Excluded(&n) => n, - Unbounded => len, - }; - assert!(start <= end); - assert!(end <= len); - - unsafe { - // set self.vec length's to start, to be safe in case Drain is leaked - self.set_len(start); - // Use the borrow in the IterMut to indicate borrowing behavior of the - // whole Drain iterator (like &mut T). - let range_slice = { - let arr = &mut self.values as &mut [ManuallyDrop<::Element>]; - slice::from_raw_parts_mut(arr.as_mut_ptr().add(start), - end - start) - }; - Drain { - tail_start: end, - tail_len: len - end, - iter: range_slice.iter(), - array_vec: NonNull::from(self), - } - } - } -} - -impl Default for ArrayVec - where A: Array { - fn default() -> Self { - ArrayVec::new() - } -} - -impl fmt::Debug for ArrayVec - where A: Array, - A::Element: fmt::Debug { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self[..].fmt(f) - } -} - -impl Deref for ArrayVec { - type Target = [A::Element]; - fn deref(&self) -> &Self::Target { - unsafe { - slice::from_raw_parts(&self.values as *const _ as *const A::Element, self.count) - } - } -} - -impl DerefMut for ArrayVec { - fn deref_mut(&mut self) -> &mut [A::Element] { - unsafe { - slice::from_raw_parts_mut(&mut self.values as *mut _ as *mut A::Element, self.count) - } - } -} - -impl Drop for ArrayVec { - fn drop(&mut self) { - unsafe { - drop_in_place(&mut self[..]) - } - } -} - -impl Extend for ArrayVec { - fn extend(&mut self, iter: I) where I: IntoIterator { - for el in iter { - self.push(el); - } - } -} - -pub struct Iter { - indices: Range, - store: A::PartialStorage, -} - -impl Drop for Iter { - fn drop(&mut self) { - self.for_each(drop); - } -} - -impl Iterator for Iter { - type Item = A::Element; - - fn next(&mut self) -> Option { - let arr = &self.store as &[ManuallyDrop<_>]; - unsafe { - self.indices.next().map(|i| ptr::read(&*arr[i])) - } - } - - fn size_hint(&self) -> (usize, Option) { - self.indices.size_hint() - } -} - -pub struct Drain<'a, A: Array> - where A::Element: 'a -{ - tail_start: usize, - tail_len: usize, - iter: slice::Iter<'a, ManuallyDrop>, - array_vec: NonNull>, -} - -impl<'a, A: Array> Iterator for Drain<'a, A> { - type Item = A::Element; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| unsafe { ptr::read(&**elt) }) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl<'a, A: Array> Drop for Drain<'a, A> { - fn drop(&mut self) { - // exhaust self first - self.for_each(drop); - - if self.tail_len > 0 { - unsafe { - let source_array_vec: &mut ArrayVec = self.array_vec.as_mut(); - // memmove back untouched tail, update to new length - let start = source_array_vec.len(); - let tail = self.tail_start; - { - let arr = - &mut source_array_vec.values as &mut [ManuallyDrop<::Element>]; - let src = arr.as_ptr().add(tail); - let dst = arr.as_mut_ptr().add(start); - ptr::copy(src, dst, self.tail_len); - }; - source_array_vec.set_len(start + self.tail_len); - } - } - } -} - -impl IntoIterator for ArrayVec { - type Item = A::Element; - type IntoIter = Iter; - fn into_iter(self) -> Self::IntoIter { - let store = unsafe { - ptr::read(&self.values) - }; - let indices = 0..self.count; - mem::forget(self); - Iter { - indices, - store, - } - } -} - -impl<'a, A: Array> IntoIterator for &'a ArrayVec { - type Item = &'a A::Element; - type IntoIter = slice::Iter<'a, A::Element>; - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { - type Item = &'a mut A::Element; - type IntoIter = slice::IterMut<'a, A::Element>; - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs new file mode 100644 index 00000000000..9eb8d0afd46 --- /dev/null +++ b/src/librustc_data_structures/bit_set.rs @@ -0,0 +1,1172 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use indexed_vec::{Idx, IndexVec}; +use rustc_serialize; +use smallvec::SmallVec; +use std::fmt; +use std::iter; +use std::marker::PhantomData; +use std::mem; +use std::slice; + +pub type Word = u64; +pub const WORD_BYTES: usize = mem::size_of::(); +pub const WORD_BITS: usize = WORD_BYTES * 8; + +/// A fixed-size bitset type with a dense representation. It does not support +/// resizing after creation; use `GrowableBitSet` for that. +/// +/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also +/// just be `usize`. +#[derive(Clone, Eq, PartialEq)] +pub struct BitSet { + words: Vec, + marker: PhantomData, +} + +impl BitSet { + #[inline] + pub fn new_empty(domain_size: usize) -> BitSet { + let num_words = num_words(domain_size); + BitSet { + words: vec![0; num_words], + marker: PhantomData, + } + } + + #[inline] + pub fn new_filled(domain_size: usize) -> BitSet { + let num_words = num_words(domain_size); + let mut result = BitSet { + words: vec![!0; num_words], + marker: PhantomData, + }; + result.clear_above(domain_size); + result + } + + #[inline] + pub fn clear(&mut self) { + for word in &mut self.words { + *word = 0; + } + } + + /// Sets all elements up to and including `size`. + pub fn set_up_to(&mut self, elem: usize) { + for word in &mut self.words { + *word = !0; + } + self.clear_above(elem); + } + + /// Clear all elements above `elem`. + fn clear_above(&mut self, elem: usize) { + let first_clear_block = elem / WORD_BITS; + + if first_clear_block < self.words.len() { + // Within `first_clear_block`, the `elem % WORD_BITS` LSBs should + // remain. + let mask = (1 << (elem % WORD_BITS)) - 1; + self.words[first_clear_block] &= mask; + + // All the blocks above `first_clear_block` are fully cleared. + for word in &mut self.words[first_clear_block + 1..] { + *word = 0; + } + } + } + + /// Efficiently overwrite `self` with `other`. Panics if `self` and `other` + /// don't have the same length. + pub fn overwrite(&mut self, other: &BitSet) { + self.words.clone_from_slice(&other.words); + } + + /// Count the number of set bits in the set. + pub fn count(&self) -> usize { + self.words.iter().map(|e| e.count_ones() as usize).sum() + } + + /// True if `self` contains `elem`. + #[inline] + pub fn contains(&self, elem: T) -> bool { + let (word_index, mask) = word_index_and_mask(elem); + (self.words[word_index] & mask) != 0 + } + + /// True if `self` is a (non-strict) superset of `other`. + /// + /// The two sets must have the same domain_size. + #[inline] + pub fn superset(&self, other: &BitSet) -> bool { + assert_eq!(self.words.len(), other.words.len()); + self.words.iter().zip(&other.words).all(|(a, b)| (a & b) == *b) + } + + /// Is the set empty? + #[inline] + pub fn is_empty(&self) -> bool { + self.words.iter().all(|a| *a == 0) + } + + /// Insert `elem`. Returns true if the set has changed. + #[inline] + pub fn insert(&mut self, elem: T) -> bool { + let (word_index, mask) = word_index_and_mask(elem); + let word_ref = &mut self.words[word_index]; + let word = *word_ref; + let new_word = word | mask; + *word_ref = new_word; + new_word != word + } + + /// Sets all bits to true. + pub fn insert_all(&mut self) { + for word in &mut self.words { + *word = !0; + } + } + + /// Returns true if the set has changed. + #[inline] + pub fn remove(&mut self, elem: T) -> bool { + let (word_index, mask) = word_index_and_mask(elem); + let word_ref = &mut self.words[word_index]; + let word = *word_ref; + let new_word = word & !mask; + *word_ref = new_word; + new_word != word + } + + /// Set `self = self | other` and return true if `self` changed + /// (i.e., if new bits were added). + pub fn union(&mut self, other: &impl UnionIntoBitSet) -> bool { + other.union_into(self) + } + + /// Set `self = self - other` and return true if `self` changed. + /// (i.e., if any bits were removed). + pub fn subtract(&mut self, other: &impl SubtractFromBitSet) -> bool { + other.subtract_from(self) + } + + /// Set `self = self & other` and return true if `self` changed. + /// (i.e., if any bits were removed). + pub fn intersect(&mut self, other: &BitSet) -> bool { + bitwise(&mut self.words, &other.words, |a, b| { a & b }) + } + + /// Get a slice of the underlying words. + pub fn words(&self) -> &[Word] { + &self.words + } + + /// Iterates over the indices of set bits in a sorted order. + #[inline] + pub fn iter<'a>(&'a self) -> BitIter<'a, T> { + BitIter { + cur: None, + iter: self.words.iter().enumerate(), + marker: PhantomData, + } + } + + /// Duplicates the set as a hybrid set. + pub fn to_hybrid(&self) -> HybridBitSet { + // This domain_size may be slightly larger than the one specified + // upon creation, due to rounding up to a whole word. That's ok. + let domain_size = self.words.len() * WORD_BITS; + + // Note: we currently don't bother trying to make a Sparse set. + HybridBitSet::Dense(self.to_owned(), domain_size) + } + + pub fn to_string(&self, bits: usize) -> String { + let mut result = String::new(); + let mut sep = '['; + + // Note: this is a little endian printout of bytes. + + // i tracks how many bits we have printed so far. + let mut i = 0; + for word in &self.words { + let mut word = *word; + for _ in 0..WORD_BYTES { // for each byte in `word`: + let remain = bits - i; + // If less than a byte remains, then mask just that many bits. + let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; + assert!(mask <= 0xFF); + let byte = word & mask; + + result.push_str(&format!("{}{:02x}", sep, byte)); + + if remain <= 8 { break; } + word >>= 8; + i += 8; + sep = '-'; + } + sep = '|'; + } + result.push(']'); + + result + } +} + +/// This is implemented by all the bitsets so that BitSet::union() can be +/// passed any type of bitset. +pub trait UnionIntoBitSet { + // Performs `other = other | self`. + fn union_into(&self, other: &mut BitSet) -> bool; +} + +/// This is implemented by all the bitsets so that BitSet::subtract() can be +/// passed any type of bitset. +pub trait SubtractFromBitSet { + // Performs `other = other - self`. + fn subtract_from(&self, other: &mut BitSet) -> bool; +} + +impl UnionIntoBitSet for BitSet { + fn union_into(&self, other: &mut BitSet) -> bool { + bitwise(&mut other.words, &self.words, |a, b| { a | b }) + } +} + +impl SubtractFromBitSet for BitSet { + fn subtract_from(&self, other: &mut BitSet) -> bool { + bitwise(&mut other.words, &self.words, |a, b| { a & !b }) + } +} + +impl fmt::Debug for BitSet { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + w.debug_list() + .entries(self.iter()) + .finish() + } +} + +impl rustc_serialize::Encodable for BitSet { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { + self.words.encode(encoder) + } +} + +impl rustc_serialize::Decodable for BitSet { + fn decode(d: &mut D) -> Result, D::Error> { + let words: Vec = rustc_serialize::Decodable::decode(d)?; + Ok(BitSet { + words, + marker: PhantomData, + }) + } +} + +pub struct BitIter<'a, T: Idx> { + cur: Option<(Word, usize)>, + iter: iter::Enumerate>, + marker: PhantomData +} + +impl<'a, T: Idx> Iterator for BitIter<'a, T> { + type Item = T; + fn next(&mut self) -> Option { + loop { + if let Some((ref mut word, offset)) = self.cur { + let bit_pos = word.trailing_zeros() as usize; + if bit_pos != WORD_BITS { + let bit = 1 << bit_pos; + *word ^= bit; + return Some(T::new(bit_pos + offset)) + } + } + + let (i, word) = self.iter.next()?; + self.cur = Some((*word, WORD_BITS * i)); + } + } +} + +pub trait BitSetOperator { + /// Combine one bitset into another. + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool; +} + +#[inline] +fn bitwise(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool + where Op: Fn(Word, Word) -> Word +{ + assert_eq!(out_vec.len(), in_vec.len()); + let mut changed = false; + for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { + let old_val = *out_elem; + let new_val = op(old_val, *in_elem); + *out_elem = new_val; + changed |= old_val != new_val; + } + changed +} + +const SPARSE_MAX: usize = 8; + +/// A fixed-size bitset type with a sparse representation and a maximum of +/// `SPARSE_MAX` elements. The elements are stored as a sorted `SmallVec` with +/// no duplicates; although `SmallVec` can spill its elements to the heap, that +/// never happens within this type because of the `SPARSE_MAX` limit. +/// +/// This type is used by `HybridBitSet`; do not use directly. +#[derive(Clone, Debug)] +pub struct SparseBitSet(SmallVec<[T; SPARSE_MAX]>); + +impl SparseBitSet { + fn new_empty() -> Self { + SparseBitSet(SmallVec::new()) + } + + fn len(&self) -> usize { + self.0.len() + } + + fn is_empty(&self) -> bool { + self.0.len() == 0 + } + + fn contains(&self, elem: T) -> bool { + self.0.contains(&elem) + } + + fn insert(&mut self, elem: T) -> bool { + assert!(self.len() < SPARSE_MAX); + if let Some(i) = self.0.iter().position(|&e| e >= elem) { + if self.0[i] == elem { + // `elem` is already in the set. + false + } else { + // `elem` is smaller than one or more existing elements. + self.0.insert(i, elem); + true + } + } else { + // `elem` is larger than all existing elements. + self.0.push(elem); + true + } + } + + fn remove(&mut self, elem: T) -> bool { + if let Some(i) = self.0.iter().position(|&e| e == elem) { + self.0.remove(i); + true + } else { + false + } + } + + fn to_dense(&self, domain_size: usize) -> BitSet { + let mut dense = BitSet::new_empty(domain_size); + for elem in self.0.iter() { + dense.insert(*elem); + } + dense + } + + fn iter(&self) -> slice::Iter { + self.0.iter() + } +} + +impl UnionIntoBitSet for SparseBitSet { + fn union_into(&self, other: &mut BitSet) -> bool { + let mut changed = false; + for elem in self.iter() { + changed |= other.insert(*elem); + } + changed + } +} + +impl SubtractFromBitSet for SparseBitSet { + fn subtract_from(&self, other: &mut BitSet) -> bool { + let mut changed = false; + for elem in self.iter() { + changed |= other.remove(*elem); + } + changed + } +} + +/// A fixed-size bitset type with a hybrid representation: sparse when there +/// are up to a `SPARSE_MAX` elements in the set, but dense when there are more +/// than `SPARSE_MAX`. +/// +/// This type is especially efficient for sets that typically have a small +/// number of elements, but a large `domain_size`, and are cleared frequently. +/// +/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also +/// just be `usize`. +#[derive(Clone, Debug)] +pub enum HybridBitSet { + Sparse(SparseBitSet, usize), + Dense(BitSet, usize), +} + +impl HybridBitSet { + // FIXME: This function is used in conjunction with `mem::replace()` in + // several pieces of awful code below. I can't work out how else to appease + // the borrow checker. + fn dummy() -> Self { + // The cheapest HybridBitSet to construct, which is only used to get + // around the borrow checker. + HybridBitSet::Sparse(SparseBitSet::new_empty(), 0) + } + + pub fn new_empty(domain_size: usize) -> Self { + HybridBitSet::Sparse(SparseBitSet::new_empty(), domain_size) + } + + pub fn domain_size(&self) -> usize { + match *self { + HybridBitSet::Sparse(_, size) => size, + HybridBitSet::Dense(_, size) => size, + } + } + + pub fn clear(&mut self) { + let domain_size = self.domain_size(); + *self = HybridBitSet::new_empty(domain_size); + } + + pub fn contains(&self, elem: T) -> bool { + match self { + HybridBitSet::Sparse(sparse, _) => sparse.contains(elem), + HybridBitSet::Dense(dense, _) => dense.contains(elem), + } + } + + pub fn superset(&self, other: &HybridBitSet) -> bool { + match (self, other) { + (HybridBitSet::Dense(self_dense, _), HybridBitSet::Dense(other_dense, _)) => { + self_dense.superset(other_dense) + } + _ => other.iter().all(|elem| self.contains(elem)), + } + } + + pub fn is_empty(&self) -> bool { + match self { + HybridBitSet::Sparse(sparse, _) => sparse.is_empty(), + HybridBitSet::Dense(dense, _) => dense.is_empty(), + } + } + + pub fn insert(&mut self, elem: T) -> bool { + match self { + HybridBitSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => { + // The set is sparse and has space for `elem`. + sparse.insert(elem) + } + HybridBitSet::Sparse(sparse, _) if sparse.contains(elem) => { + // The set is sparse and does not have space for `elem`, but + // that doesn't matter because `elem` is already present. + false + } + HybridBitSet::Sparse(_, _) => { + // The set is sparse and full. Convert to a dense set. + match mem::replace(self, HybridBitSet::dummy()) { + HybridBitSet::Sparse(sparse, domain_size) => { + let mut dense = sparse.to_dense(domain_size); + let changed = dense.insert(elem); + assert!(changed); + *self = HybridBitSet::Dense(dense, domain_size); + changed + } + _ => unreachable!() + } + } + + HybridBitSet::Dense(dense, _) => dense.insert(elem), + } + } + + pub fn insert_all(&mut self) { + let domain_size = self.domain_size(); + match self { + HybridBitSet::Sparse(_, _) => { + let dense = BitSet::new_filled(domain_size); + *self = HybridBitSet::Dense(dense, domain_size); + } + HybridBitSet::Dense(dense, _) => dense.insert_all(), + } + } + + pub fn remove(&mut self, elem: T) -> bool { + // Note: we currently don't bother going from Dense back to Sparse. + match self { + HybridBitSet::Sparse(sparse, _) => sparse.remove(elem), + HybridBitSet::Dense(dense, _) => dense.remove(elem), + } + } + + pub fn union(&mut self, other: &HybridBitSet) -> bool { + match self { + HybridBitSet::Sparse(_, _) => { + match other { + HybridBitSet::Sparse(other_sparse, _) => { + // Both sets are sparse. Add the elements in + // `other_sparse` to `self_hybrid` one at a time. This + // may or may not cause `self_hybrid` to be densified. + let mut self_hybrid = mem::replace(self, HybridBitSet::dummy()); + let mut changed = false; + for elem in other_sparse.iter() { + changed |= self_hybrid.insert(*elem); + } + *self = self_hybrid; + changed + } + HybridBitSet::Dense(other_dense, _) => { + // `self` is sparse and `other` is dense. Densify + // `self` and then do the bitwise union. + match mem::replace(self, HybridBitSet::dummy()) { + HybridBitSet::Sparse(self_sparse, self_domain_size) => { + let mut new_dense = self_sparse.to_dense(self_domain_size); + let changed = new_dense.union(other_dense); + *self = HybridBitSet::Dense(new_dense, self_domain_size); + changed + } + _ => unreachable!() + } + } + } + } + + HybridBitSet::Dense(self_dense, _) => self_dense.union(other), + } + } + + /// Converts to a dense set, consuming itself in the process. + pub fn to_dense(self) -> BitSet { + match self { + HybridBitSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size), + HybridBitSet::Dense(dense, _) => dense, + } + } + + pub fn iter(&self) -> HybridIter { + match self { + HybridBitSet::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()), + HybridBitSet::Dense(dense, _) => HybridIter::Dense(dense.iter()), + } + } +} + +impl UnionIntoBitSet for HybridBitSet { + fn union_into(&self, other: &mut BitSet) -> bool { + match self { + HybridBitSet::Sparse(sparse, _) => sparse.union_into(other), + HybridBitSet::Dense(dense, _) => dense.union_into(other), + } + } +} + +impl SubtractFromBitSet for HybridBitSet { + fn subtract_from(&self, other: &mut BitSet) -> bool { + match self { + HybridBitSet::Sparse(sparse, _) => sparse.subtract_from(other), + HybridBitSet::Dense(dense, _) => dense.subtract_from(other), + } + } +} + +pub enum HybridIter<'a, T: Idx> { + Sparse(slice::Iter<'a, T>), + Dense(BitIter<'a, T>), +} + +impl<'a, T: Idx> Iterator for HybridIter<'a, T> { + type Item = T; + + fn next(&mut self) -> Option { + match self { + HybridIter::Sparse(sparse) => sparse.next().map(|e| *e), + HybridIter::Dense(dense) => dense.next(), + } + } +} + +/// A resizable bitset type with a dense representation. +/// +/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also +/// just be `usize`. +#[derive(Clone, Debug, PartialEq)] +pub struct GrowableBitSet { + bit_set: BitSet, +} + +impl GrowableBitSet { + pub fn grow(&mut self, domain_size: T) { + let num_words = num_words(domain_size); + if self.bit_set.words.len() <= num_words { + self.bit_set.words.resize(num_words + 1, 0) + } + } + + pub fn new_empty() -> GrowableBitSet { + GrowableBitSet { bit_set: BitSet::new_empty(0) } + } + + pub fn with_capacity(bits: usize) -> GrowableBitSet { + GrowableBitSet { bit_set: BitSet::new_empty(bits) } + } + + /// Returns true if the set has changed. + #[inline] + pub fn insert(&mut self, elem: T) -> bool { + self.grow(elem); + self.bit_set.insert(elem) + } + + #[inline] + pub fn contains(&self, elem: T) -> bool { + let (word_index, mask) = word_index_and_mask(elem); + if let Some(word) = self.bit_set.words.get(word_index) { + (word & mask) != 0 + } else { + false + } + } +} + +/// A fixed-size 2D bit matrix type with a dense representation. +/// +/// `R` and `C` are index types used to identify rows and columns respectively; +/// typically newtyped `usize` wrappers, but they can also just be `usize`. +/// +#[derive(Clone, Debug)] +pub struct BitMatrix { + columns: usize, + words: Vec, + marker: PhantomData<(R, C)>, +} + +impl BitMatrix { + /// Create a new `rows x columns` matrix, initially empty. + pub fn new(rows: usize, columns: usize) -> BitMatrix { + // For every element, we need one bit for every other + // element. Round up to an even number of words. + let words_per_row = num_words(columns); + BitMatrix { + columns, + words: vec![0; rows * words_per_row], + marker: PhantomData, + } + } + + /// The range of bits for a given row. + fn range(&self, row: R) -> (usize, usize) { + let row = row.index(); + let words_per_row = num_words(self.columns); + let start = row * words_per_row; + (start, start + words_per_row) + } + + /// Sets the cell at `(row, column)` to true. Put another way, insert + /// `column` to the bitset for `row`. + /// + /// Returns true if this changed the matrix, and false otherwise. + pub fn insert(&mut self, row: R, column: R) -> bool { + let (start, _) = self.range(row); + let (word_index, mask) = word_index_and_mask(column); + let words = &mut self.words[..]; + let word = words[start + word_index]; + let new_word = word | mask; + words[start + word_index] = new_word; + word != new_word + } + + /// Do the bits from `row` contain `column`? Put another way, is + /// the matrix cell at `(row, column)` true? Put yet another way, + /// if the matrix represents (transitive) reachability, can + /// `row` reach `column`? + pub fn contains(&self, row: R, column: R) -> bool { + let (start, _) = self.range(row); + let (word_index, mask) = word_index_and_mask(column); + (self.words[start + word_index] & mask) != 0 + } + + /// Returns those indices that are true in rows `a` and `b`. This + /// is an O(n) operation where `n` is the number of elements + /// (somewhat independent from the actual size of the + /// intersection, in particular). + pub fn intersect_rows(&self, a: R, b: R) -> Vec { + let (a_start, a_end) = self.range(a); + let (b_start, b_end) = self.range(b); + let mut result = Vec::with_capacity(self.columns); + for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() { + let mut v = self.words[i] & self.words[j]; + for bit in 0..WORD_BITS { + if v == 0 { + break; + } + if v & 0x1 != 0 { + result.push(C::new(base * WORD_BITS + bit)); + } + v >>= 1; + } + } + result + } + + /// Add the bits from row `read` to the bits from row `write`, + /// return true if anything changed. + /// + /// This is used when computing transitive reachability because if + /// you have an edge `write -> read`, because in that case + /// `write` can reach everything that `read` can (and + /// potentially more). + pub fn union_rows(&mut self, read: R, write: R) -> bool { + let (read_start, read_end) = self.range(read); + let (write_start, write_end) = self.range(write); + let words = &mut self.words[..]; + let mut changed = false; + for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) { + let word = words[write_index]; + let new_word = word | words[read_index]; + words[write_index] = new_word; + changed |= word != new_word; + } + changed + } + + /// Iterates through all the columns set to true in a given row of + /// the matrix. + pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> { + let (start, end) = self.range(row); + BitIter { + cur: None, + iter: self.words[start..end].iter().enumerate(), + marker: PhantomData, + } + } +} + +/// A fixed-column-size, variable-row-size 2D bit matrix with a moderately +/// sparse representation. +/// +/// Initially, every row has no explicit representation. If any bit within a +/// row is set, the entire row is instantiated as `Some()`. +/// Furthermore, any previously uninstantiated rows prior to it will be +/// instantiated as `None`. Those prior rows may themselves become fully +/// instantiated later on if any of their bits are set. +/// +/// `R` and `C` are index types used to identify rows and columns respectively; +/// typically newtyped `usize` wrappers, but they can also just be `usize`. +#[derive(Clone, Debug)] +pub struct SparseBitMatrix +where + R: Idx, + C: Idx, +{ + num_columns: usize, + rows: IndexVec>>, +} + +impl SparseBitMatrix { + /// Create a new empty sparse bit matrix with no rows or columns. + pub fn new(num_columns: usize) -> Self { + Self { + num_columns, + rows: IndexVec::new(), + } + } + + fn ensure_row(&mut self, row: R) -> &mut HybridBitSet { + // Instantiate any missing rows up to and including row `row` with an + // empty HybridBitSet. + self.rows.ensure_contains_elem(row, || None); + + // Then replace row `row` with a full HybridBitSet if necessary. + let num_columns = self.num_columns; + self.rows[row].get_or_insert_with(|| HybridBitSet::new_empty(num_columns)) + } + + /// Sets the cell at `(row, column)` to true. Put another way, insert + /// `column` to the bitset for `row`. + /// + /// Returns true if this changed the matrix, and false otherwise. + pub fn insert(&mut self, row: R, column: C) -> bool { + self.ensure_row(row).insert(column) + } + + /// Do the bits from `row` contain `column`? Put another way, is + /// the matrix cell at `(row, column)` true? Put yet another way, + /// if the matrix represents (transitive) reachability, can + /// `row` reach `column`? + pub fn contains(&self, row: R, column: C) -> bool { + self.row(row).map_or(false, |r| r.contains(column)) + } + + /// Add the bits from row `read` to the bits from row `write`, + /// return true if anything changed. + /// + /// This is used when computing transitive reachability because if + /// you have an edge `write -> read`, because in that case + /// `write` can reach everything that `read` can (and + /// potentially more). + pub fn union_rows(&mut self, read: R, write: R) -> bool { + if read == write || self.row(read).is_none() { + return false; + } + + self.ensure_row(write); + if let (Some(read_row), Some(write_row)) = self.rows.pick2_mut(read, write) { + write_row.union(read_row) + } else { + unreachable!() + } + } + + /// Union a row, `from`, into the `into` row. + pub fn union_into_row(&mut self, into: R, from: &HybridBitSet) -> bool { + self.ensure_row(into).union(from) + } + + /// Insert all bits in the given row. + pub fn insert_all_into_row(&mut self, row: R) { + self.ensure_row(row).insert_all(); + } + + pub fn rows(&self) -> impl Iterator { + self.rows.indices() + } + + /// Iterates through all the columns set to true in a given row of + /// the matrix. + pub fn iter<'a>(&'a self, row: R) -> impl Iterator + 'a { + self.row(row).into_iter().flat_map(|r| r.iter()) + } + + pub fn row(&self, row: R) -> Option<&HybridBitSet> { + if let Some(Some(row)) = self.rows.get(row) { + Some(row) + } else { + None + } + } +} + +#[inline] +fn num_words(elements: T) -> usize { + (elements.index() + WORD_BITS - 1) / WORD_BITS +} + +#[inline] +fn word_index_and_mask(index: T) -> (usize, Word) { + let index = index.index(); + let word_index = index / WORD_BITS; + let mask = 1 << (index % WORD_BITS); + (word_index, mask) +} + +#[test] +fn test_clear_above() { + use std::cmp; + + for i in 0..256 { + let mut idx_buf: BitSet = BitSet::new_filled(128); + idx_buf.clear_above(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..cmp::min(i, 128)).collect(); + assert_eq!(elems, expected); + } +} + +#[test] +fn test_set_up_to() { + for i in 0..128 { + for mut idx_buf in + vec![BitSet::new_empty(128), BitSet::new_filled(128)].into_iter() + { + idx_buf.set_up_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } + } +} + +#[test] +fn test_new_filled() { + for i in 0..128 { + let idx_buf = BitSet::new_filled(i); + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } +} + +#[test] +fn bitset_iter_works() { + let mut bitset: BitSet = BitSet::new_empty(100); + bitset.insert(1); + bitset.insert(10); + bitset.insert(19); + bitset.insert(62); + bitset.insert(63); + bitset.insert(64); + bitset.insert(65); + bitset.insert(66); + bitset.insert(99); + assert_eq!( + bitset.iter().collect::>(), + [1, 10, 19, 62, 63, 64, 65, 66, 99] + ); +} + +#[test] +fn bitset_iter_works_2() { + let mut bitset: BitSet = BitSet::new_empty(319); + bitset.insert(0); + bitset.insert(127); + bitset.insert(191); + bitset.insert(255); + bitset.insert(319); + assert_eq!(bitset.iter().collect::>(), [0, 127, 191, 255, 319]); +} + +#[test] +fn union_two_sets() { + let mut set1: BitSet = BitSet::new_empty(65); + let mut set2: BitSet = BitSet::new_empty(65); + assert!(set1.insert(3)); + assert!(!set1.insert(3)); + assert!(set2.insert(5)); + assert!(set2.insert(64)); + assert!(set1.union(&set2)); + assert!(!set1.union(&set2)); + assert!(set1.contains(3)); + assert!(!set1.contains(4)); + assert!(set1.contains(5)); + assert!(!set1.contains(63)); + assert!(set1.contains(64)); +} + +#[test] +fn hybrid_bitset() { + let mut sparse038: HybridBitSet = HybridBitSet::new_empty(256); + assert!(sparse038.is_empty()); + assert!(sparse038.insert(0)); + assert!(sparse038.insert(1)); + assert!(sparse038.insert(8)); + assert!(sparse038.insert(3)); + assert!(!sparse038.insert(3)); + assert!(sparse038.remove(1)); + assert!(!sparse038.is_empty()); + assert_eq!(sparse038.iter().collect::>(), [0, 3, 8]); + + for i in 0..256 { + if i == 0 || i == 3 || i == 8 { + assert!(sparse038.contains(i)); + } else { + assert!(!sparse038.contains(i)); + } + } + + let mut sparse01358 = sparse038.clone(); + assert!(sparse01358.insert(1)); + assert!(sparse01358.insert(5)); + assert_eq!(sparse01358.iter().collect::>(), [0, 1, 3, 5, 8]); + + let mut dense10 = HybridBitSet::new_empty(256); + for i in 0..10 { + assert!(dense10.insert(i)); + } + assert!(!dense10.is_empty()); + assert_eq!(dense10.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut dense256 = HybridBitSet::new_empty(256); + assert!(dense256.is_empty()); + dense256.insert_all(); + assert!(!dense256.is_empty()); + for i in 0..256 { + assert!(dense256.contains(i)); + } + + assert!(sparse038.superset(&sparse038)); // sparse + sparse (self) + assert!(sparse01358.superset(&sparse038)); // sparse + sparse + assert!(dense10.superset(&sparse038)); // dense + sparse + assert!(dense10.superset(&dense10)); // dense + dense (self) + assert!(dense256.superset(&dense10)); // dense + dense + + let mut hybrid = sparse038; + assert!(!sparse01358.union(&hybrid)); // no change + assert!(hybrid.union(&sparse01358)); + assert!(hybrid.superset(&sparse01358) && sparse01358.superset(&hybrid)); + assert!(!dense10.union(&sparse01358)); + assert!(!dense256.union(&dense10)); + let mut dense = dense10; + assert!(dense.union(&dense256)); + assert!(dense.superset(&dense256) && dense256.superset(&dense)); + assert!(hybrid.union(&dense256)); + assert!(hybrid.superset(&dense256) && dense256.superset(&hybrid)); + + assert_eq!(dense256.iter().count(), 256); + let mut dense0 = dense256; + for i in 0..256 { + assert!(dense0.remove(i)); + } + assert!(!dense0.remove(0)); + assert!(dense0.is_empty()); +} + +#[test] +fn grow() { + let mut set: GrowableBitSet = GrowableBitSet::with_capacity(65); + for index in 0..65 { + assert!(set.insert(index)); + assert!(!set.insert(index)); + } + set.grow(128); + + // Check if the bits set before growing are still set + for index in 0..65 { + assert!(set.contains(index)); + } + + // Check if the new bits are all un-set + for index in 65..128 { + assert!(!set.contains(index)); + } + + // Check that we can set all new bits without running out of bounds + for index in 65..128 { + assert!(set.insert(index)); + assert!(!set.insert(index)); + } +} + +#[test] +fn matrix_intersection() { + let mut matrix: BitMatrix = BitMatrix::new(200, 200); + + // (*) Elements reachable from both 2 and 65. + + matrix.insert(2, 3); + matrix.insert(2, 6); + matrix.insert(2, 10); // (*) + matrix.insert(2, 64); // (*) + matrix.insert(2, 65); + matrix.insert(2, 130); + matrix.insert(2, 160); // (*) + + matrix.insert(64, 133); + + matrix.insert(65, 2); + matrix.insert(65, 8); + matrix.insert(65, 10); // (*) + matrix.insert(65, 64); // (*) + matrix.insert(65, 68); + matrix.insert(65, 133); + matrix.insert(65, 160); // (*) + + let intersection = matrix.intersect_rows(2, 64); + assert!(intersection.is_empty()); + + let intersection = matrix.intersect_rows(2, 65); + assert_eq!(intersection, &[10, 64, 160]); +} + +#[test] +fn matrix_iter() { + let mut matrix: BitMatrix = BitMatrix::new(64, 100); + matrix.insert(3, 22); + matrix.insert(3, 75); + matrix.insert(2, 99); + matrix.insert(4, 0); + matrix.union_rows(3, 5); + + let expected = [99]; + let mut iter = expected.iter(); + for i in matrix.iter(2) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); + + let expected = [22, 75]; + let mut iter = expected.iter(); + for i in matrix.iter(3) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); + + let expected = [0]; + let mut iter = expected.iter(); + for i in matrix.iter(4) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); + + let expected = [22, 75]; + let mut iter = expected.iter(); + for i in matrix.iter(5) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); +} + +#[test] +fn sparse_matrix_iter() { + let mut matrix: SparseBitMatrix = SparseBitMatrix::new(100); + matrix.insert(3, 22); + matrix.insert(3, 75); + matrix.insert(2, 99); + matrix.insert(4, 0); + matrix.union_rows(3, 5); + + let expected = [99]; + let mut iter = expected.iter(); + for i in matrix.iter(2) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); + + let expected = [22, 75]; + let mut iter = expected.iter(); + for i in matrix.iter(3) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); + + let expected = [0]; + let mut iter = expected.iter(); + for i in matrix.iter(4) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); + + let expected = [22, 75]; + let mut iter = expected.iter(); + for i in matrix.iter(5) { + let j = *iter.next().unwrap(); + assert_eq!(i, j); + } + assert!(iter.next().is_none()); +} diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs deleted file mode 100644 index 52cc347f8e7..00000000000 --- a/src/librustc_data_structures/bitvec.rs +++ /dev/null @@ -1,781 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use indexed_vec::{Idx, IndexVec}; -use rustc_serialize; -use std::iter; -use std::marker::PhantomData; -use std::slice; - -pub type Word = u64; -pub const WORD_BYTES: usize = ::std::mem::size_of::(); -pub const WORD_BITS: usize = WORD_BYTES * 8; - -/// A very simple BitArray type. -/// -/// It does not support resizing after creation; use `BitVector` for that. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct BitArray { - data: Vec, - marker: PhantomData, -} - -impl BitArray { - // Do not make this method public, instead switch your use case to BitVector. - #[inline] - fn grow(&mut self, num_bits: C) { - let num_words = num_words(num_bits); - if self.data.len() <= num_words { - self.data.resize(num_words + 1, 0) - } - } - - #[inline] - pub fn new(num_bits: usize) -> BitArray { - BitArray::new_empty(num_bits) - } - - #[inline] - pub fn new_empty(num_bits: usize) -> BitArray { - let num_words = num_words(num_bits); - BitArray { - data: vec![0; num_words], - marker: PhantomData, - } - } - - #[inline] - pub fn new_filled(num_bits: usize) -> BitArray { - let num_words = num_words(num_bits); - let mut result = BitArray { - data: vec![!0; num_words], - marker: PhantomData, - }; - result.clear_above(num_bits); - result - } - - #[inline] - pub fn clear(&mut self) { - for p in &mut self.data { - *p = 0; - } - } - - /// Sets all elements up to `num_bits`. - pub fn set_up_to(&mut self, num_bits: usize) { - for p in &mut self.data { - *p = !0; - } - self.clear_above(num_bits); - } - - /// Clear all elements above `num_bits`. - fn clear_above(&mut self, num_bits: usize) { - let first_clear_block = num_bits / WORD_BITS; - - if first_clear_block < self.data.len() { - // Within `first_clear_block`, the `num_bits % WORD_BITS` LSBs - // should remain. - let mask = (1 << (num_bits % WORD_BITS)) - 1; - self.data[first_clear_block] &= mask; - - // All the blocks above `first_clear_block` are fully cleared. - for b in &mut self.data[first_clear_block + 1..] { - *b = 0; - } - } - } - - pub fn count(&self) -> usize { - self.data.iter().map(|e| e.count_ones() as usize).sum() - } - - /// True if `self` contains the bit `bit`. - #[inline] - pub fn contains(&self, bit: C) -> bool { - let (word, mask) = word_mask(bit); - (self.data[word] & mask) != 0 - } - - /// True if `self` contains all the bits in `other`. - /// - /// The two vectors must have the same length. - #[inline] - pub fn contains_all(&self, other: &BitArray) -> bool { - assert_eq!(self.data.len(), other.data.len()); - self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b) - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.data.iter().all(|a| *a == 0) - } - - /// Returns true if the bit has changed. - #[inline] - pub fn insert(&mut self, bit: C) -> bool { - let (word, mask) = word_mask(bit); - let data = &mut self.data[word]; - let value = *data; - let new_value = value | mask; - *data = new_value; - new_value != value - } - - /// Sets all bits to true. - pub fn insert_all(&mut self) { - for data in &mut self.data { - *data = !0; - } - } - - /// Returns true if the bit has changed. - #[inline] - pub fn remove(&mut self, bit: C) -> bool { - let (word, mask) = word_mask(bit); - let data = &mut self.data[word]; - let value = *data; - let new_value = value & !mask; - *data = new_value; - new_value != value - } - - #[inline] - pub fn merge(&mut self, all: &BitArray) -> bool { - assert!(self.data.len() == all.data.len()); - let mut changed = false; - for (i, j) in self.data.iter_mut().zip(&all.data) { - let value = *i; - *i = value | *j; - if value != *i { - changed = true; - } - } - changed - } - - pub fn words(&self) -> &[Word] { - &self.data - } - - pub fn words_mut(&mut self) -> &mut [Word] { - &mut self.data - } - - /// Iterates over indexes of set bits in a sorted order - #[inline] - pub fn iter<'a>(&'a self) -> BitIter<'a, C> { - BitIter { - cur: None, - iter: self.data.iter().enumerate(), - marker: PhantomData, - } - } -} - -impl rustc_serialize::Encodable for BitArray { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { - self.data.encode(encoder) - } -} - -impl rustc_serialize::Decodable for BitArray { - fn decode(d: &mut D) -> Result, D::Error> { - let words: Vec = rustc_serialize::Decodable::decode(d)?; - Ok(BitArray { - data: words, - marker: PhantomData, - }) - } -} - -pub struct BitIter<'a, C: Idx> { - cur: Option<(Word, usize)>, - iter: iter::Enumerate>, - marker: PhantomData -} - -impl<'a, C: Idx> Iterator for BitIter<'a, C> { - type Item = C; - fn next(&mut self) -> Option { - loop { - if let Some((ref mut word, offset)) = self.cur { - let bit_pos = word.trailing_zeros() as usize; - if bit_pos != WORD_BITS { - let bit = 1 << bit_pos; - *word ^= bit; - return Some(C::new(bit_pos + offset)) - } - } - - let (i, word) = self.iter.next()?; - self.cur = Some((*word, WORD_BITS * i)); - } - } -} - -pub trait BitwiseOperator { - /// Applies some bit-operation pointwise to each of the bits in the two inputs. - fn join(&self, pred1: Word, pred2: Word) -> Word; -} - -#[inline] -pub fn bitwise(out_vec: &mut [Word], in_vec: &[Word], op: &Op) -> bool -{ - assert_eq!(out_vec.len(), in_vec.len()); - let mut changed = false; - for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { - let old_val = *out_elem; - let new_val = op.join(old_val, *in_elem); - *out_elem = new_val; - changed |= old_val != new_val; - } - changed -} - -pub struct Intersect; -impl BitwiseOperator for Intersect { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a & b } -} - -pub struct Union; -impl BitwiseOperator for Union { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a | b } -} - -pub struct Subtract; -impl BitwiseOperator for Subtract { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a & !b } -} - -pub fn bits_to_string(words: &[Word], bits: usize) -> String { - let mut result = String::new(); - let mut sep = '['; - - // Note: this is a little endian printout of bytes. - - // i tracks how many bits we have printed so far. - let mut i = 0; - for &word in words.iter() { - let mut v = word; - for _ in 0..WORD_BYTES { // for each byte in `v`: - let remain = bits - i; - // If less than a byte remains, then mask just that many bits. - let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; - assert!(mask <= 0xFF); - let byte = v & mask; - - result.push_str(&format!("{}{:02x}", sep, byte)); - - if remain <= 8 { break; } - v >>= 8; - i += 8; - sep = '-'; - } - sep = '|'; - } - result.push(']'); - - result -} - -/// A resizable BitVector type. -#[derive(Clone, Debug, PartialEq)] -pub struct BitVector { - data: BitArray, -} - -impl BitVector { - pub fn grow(&mut self, num_bits: C) { - self.data.grow(num_bits) - } - - pub fn new() -> BitVector { - BitVector { data: BitArray::new(0) } - } - - pub fn with_capacity(bits: usize) -> BitVector { - BitVector { data: BitArray::new(bits) } - } - - /// Returns true if the bit has changed. - #[inline] - pub fn insert(&mut self, bit: C) -> bool { - self.grow(bit); - self.data.insert(bit) - } - - #[inline] - pub fn contains(&self, bit: C) -> bool { - let (word, mask) = word_mask(bit); - if let Some(word) = self.data.data.get(word) { - (word & mask) != 0 - } else { - false - } - } -} - -/// A "bit matrix" is basically a matrix of booleans represented as -/// one gigantic bitvector. In other words, it is as if you have -/// `rows` bitvectors, each of length `columns`. -#[derive(Clone, Debug)] -pub struct BitMatrix { - columns: usize, - vector: Vec, - phantom: PhantomData<(R, C)>, -} - -impl BitMatrix { - /// Create a new `rows x columns` matrix, initially empty. - pub fn new(rows: usize, columns: usize) -> BitMatrix { - // For every element, we need one bit for every other - // element. Round up to an even number of words. - let words_per_row = num_words(columns); - BitMatrix { - columns, - vector: vec![0; rows * words_per_row], - phantom: PhantomData, - } - } - - /// The range of bits for a given row. - fn range(&self, row: R) -> (usize, usize) { - let row = row.index(); - let words_per_row = num_words(self.columns); - let start = row * words_per_row; - (start, start + words_per_row) - } - - /// Sets the cell at `(row, column)` to true. Put another way, add - /// `column` to the bitset for `row`. - /// - /// Returns true if this changed the matrix, and false otherwise. - pub fn add(&mut self, row: R, column: R) -> bool { - let (start, _) = self.range(row); - let (word, mask) = word_mask(column); - let vector = &mut self.vector[..]; - let v1 = vector[start + word]; - let v2 = v1 | mask; - vector[start + word] = v2; - v1 != v2 - } - - /// Do the bits from `row` contain `column`? Put another way, is - /// the matrix cell at `(row, column)` true? Put yet another way, - /// if the matrix represents (transitive) reachability, can - /// `row` reach `column`? - pub fn contains(&self, row: R, column: R) -> bool { - let (start, _) = self.range(row); - let (word, mask) = word_mask(column); - (self.vector[start + word] & mask) != 0 - } - - /// Returns those indices that are true in rows `a` and `b`. This - /// is an O(n) operation where `n` is the number of elements - /// (somewhat independent from the actual size of the - /// intersection, in particular). - pub fn intersection(&self, a: R, b: R) -> Vec { - let (a_start, a_end) = self.range(a); - let (b_start, b_end) = self.range(b); - let mut result = Vec::with_capacity(self.columns); - for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() { - let mut v = self.vector[i] & self.vector[j]; - for bit in 0..WORD_BITS { - if v == 0 { - break; - } - if v & 0x1 != 0 { - result.push(C::new(base * WORD_BITS + bit)); - } - v >>= 1; - } - } - result - } - - /// Add the bits from row `read` to the bits from row `write`, - /// return true if anything changed. - /// - /// This is used when computing transitive reachability because if - /// you have an edge `write -> read`, because in that case - /// `write` can reach everything that `read` can (and - /// potentially more). - pub fn merge(&mut self, read: R, write: R) -> bool { - let (read_start, read_end) = self.range(read); - let (write_start, write_end) = self.range(write); - let vector = &mut self.vector[..]; - let mut changed = false; - for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) { - let v1 = vector[write_index]; - let v2 = v1 | vector[read_index]; - vector[write_index] = v2; - changed |= v1 != v2; - } - changed - } - - /// Iterates through all the columns set to true in a given row of - /// the matrix. - pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> { - let (start, end) = self.range(row); - BitIter { - cur: None, - iter: self.vector[start..end].iter().enumerate(), - marker: PhantomData, - } - } -} - -/// A moderately sparse bit matrix, in which rows are instantiated lazily. -/// -/// Initially, every row has no explicit representation. If any bit within a -/// row is set, the entire row is instantiated as -/// `Some()`. Furthermore, any previously -/// uninstantiated rows prior to it will be instantiated as `None`. Those prior -/// rows may themselves become fully instantiated later on if any of their bits -/// are set. -#[derive(Clone, Debug)] -pub struct SparseBitMatrix -where - R: Idx, - C: Idx, -{ - num_columns: usize, - rows: IndexVec>>, -} - -impl SparseBitMatrix { - /// Create a new empty sparse bit matrix with no rows or columns. - pub fn new(num_columns: usize) -> Self { - Self { - num_columns, - rows: IndexVec::new(), - } - } - - fn ensure_row(&mut self, row: R) -> &mut BitArray { - // Instantiate any missing rows up to and including row `row` with an - // empty BitArray. - self.rows.ensure_contains_elem(row, || None); - - // Then replace row `row` with a full BitArray if necessary. - let num_columns = self.num_columns; - self.rows[row].get_or_insert_with(|| BitArray::new(num_columns)) - } - - /// Sets the cell at `(row, column)` to true. Put another way, insert - /// `column` to the bitset for `row`. - /// - /// Returns true if this changed the matrix, and false otherwise. - pub fn add(&mut self, row: R, column: C) -> bool { - self.ensure_row(row).insert(column) - } - - /// Do the bits from `row` contain `column`? Put another way, is - /// the matrix cell at `(row, column)` true? Put yet another way, - /// if the matrix represents (transitive) reachability, can - /// `row` reach `column`? - pub fn contains(&self, row: R, column: C) -> bool { - self.row(row).map_or(false, |r| r.contains(column)) - } - - /// Add the bits from row `read` to the bits from row `write`, - /// return true if anything changed. - /// - /// This is used when computing transitive reachability because if - /// you have an edge `write -> read`, because in that case - /// `write` can reach everything that `read` can (and - /// potentially more). - pub fn merge(&mut self, read: R, write: R) -> bool { - if read == write || self.row(read).is_none() { - return false; - } - - self.ensure_row(write); - if let (Some(bitvec_read), Some(bitvec_write)) = self.rows.pick2_mut(read, write) { - bitvec_write.merge(bitvec_read) - } else { - unreachable!() - } - } - - /// Merge a row, `from`, into the `into` row. - pub fn merge_into(&mut self, into: R, from: &BitArray) -> bool { - self.ensure_row(into).merge(from) - } - - /// Add all bits to the given row. - pub fn add_all(&mut self, row: R) { - self.ensure_row(row).insert_all(); - } - - pub fn rows(&self) -> impl Iterator { - self.rows.indices() - } - - /// Iterates through all the columns set to true in a given row of - /// the matrix. - pub fn iter<'a>(&'a self, row: R) -> impl Iterator + 'a { - self.row(row).into_iter().flat_map(|r| r.iter()) - } - - pub fn row(&self, row: R) -> Option<&BitArray> { - if let Some(Some(row)) = self.rows.get(row) { - Some(row) - } else { - None - } - } -} - -#[inline] -fn num_words(elements: C) -> usize { - (elements.index() + WORD_BITS - 1) / WORD_BITS -} - -#[inline] -fn word_mask(index: C) -> (usize, Word) { - let index = index.index(); - let word = index / WORD_BITS; - let mask = 1 << (index % WORD_BITS); - (word, mask) -} - -#[test] -fn test_clear_above() { - use std::cmp; - - for i in 0..256 { - let mut idx_buf: BitArray = BitArray::new_filled(128); - idx_buf.clear_above(i); - - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..cmp::min(i, 128)).collect(); - assert_eq!(elems, expected); - } -} - -#[test] -fn test_set_up_to() { - for i in 0..128 { - for mut idx_buf in - vec![BitArray::new_empty(128), BitArray::new_filled(128)] - .into_iter() - { - idx_buf.set_up_to(i); - - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..i).collect(); - assert_eq!(elems, expected); - } - } -} - -#[test] -fn test_new_filled() { - for i in 0..128 { - let idx_buf = BitArray::new_filled(i); - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..i).collect(); - assert_eq!(elems, expected); - } -} - -#[test] -fn bitvec_iter_works() { - let mut bitvec: BitArray = BitArray::new(100); - bitvec.insert(1); - bitvec.insert(10); - bitvec.insert(19); - bitvec.insert(62); - bitvec.insert(63); - bitvec.insert(64); - bitvec.insert(65); - bitvec.insert(66); - bitvec.insert(99); - assert_eq!( - bitvec.iter().collect::>(), - [1, 10, 19, 62, 63, 64, 65, 66, 99] - ); -} - -#[test] -fn bitvec_iter_works_2() { - let mut bitvec: BitArray = BitArray::new(319); - bitvec.insert(0); - bitvec.insert(127); - bitvec.insert(191); - bitvec.insert(255); - bitvec.insert(319); - assert_eq!(bitvec.iter().collect::>(), [0, 127, 191, 255, 319]); -} - -#[test] -fn union_two_vecs() { - let mut vec1: BitArray = BitArray::new(65); - let mut vec2: BitArray = BitArray::new(65); - assert!(vec1.insert(3)); - assert!(!vec1.insert(3)); - assert!(vec2.insert(5)); - assert!(vec2.insert(64)); - assert!(vec1.merge(&vec2)); - assert!(!vec1.merge(&vec2)); - assert!(vec1.contains(3)); - assert!(!vec1.contains(4)); - assert!(vec1.contains(5)); - assert!(!vec1.contains(63)); - assert!(vec1.contains(64)); -} - -#[test] -fn grow() { - let mut vec1: BitVector = BitVector::with_capacity(65); - for index in 0..65 { - assert!(vec1.insert(index)); - assert!(!vec1.insert(index)); - } - vec1.grow(128); - - // Check if the bits set before growing are still set - for index in 0..65 { - assert!(vec1.contains(index)); - } - - // Check if the new bits are all un-set - for index in 65..128 { - assert!(!vec1.contains(index)); - } - - // Check that we can set all new bits without running out of bounds - for index in 65..128 { - assert!(vec1.insert(index)); - assert!(!vec1.insert(index)); - } -} - -#[test] -fn matrix_intersection() { - let mut vec1: BitMatrix = BitMatrix::new(200, 200); - - // (*) Elements reachable from both 2 and 65. - - vec1.add(2, 3); - vec1.add(2, 6); - vec1.add(2, 10); // (*) - vec1.add(2, 64); // (*) - vec1.add(2, 65); - vec1.add(2, 130); - vec1.add(2, 160); // (*) - - vec1.add(64, 133); - - vec1.add(65, 2); - vec1.add(65, 8); - vec1.add(65, 10); // (*) - vec1.add(65, 64); // (*) - vec1.add(65, 68); - vec1.add(65, 133); - vec1.add(65, 160); // (*) - - let intersection = vec1.intersection(2, 64); - assert!(intersection.is_empty()); - - let intersection = vec1.intersection(2, 65); - assert_eq!(intersection, &[10, 64, 160]); -} - -#[test] -fn matrix_iter() { - let mut matrix: BitMatrix = BitMatrix::new(64, 100); - matrix.add(3, 22); - matrix.add(3, 75); - matrix.add(2, 99); - matrix.add(4, 0); - matrix.merge(3, 5); - - let expected = [99]; - let mut iter = expected.iter(); - for i in matrix.iter(2) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); - - let expected = [22, 75]; - let mut iter = expected.iter(); - for i in matrix.iter(3) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); - - let expected = [0]; - let mut iter = expected.iter(); - for i in matrix.iter(4) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); - - let expected = [22, 75]; - let mut iter = expected.iter(); - for i in matrix.iter(5) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); -} - -#[test] -fn sparse_matrix_iter() { - let mut matrix: SparseBitMatrix = SparseBitMatrix::new(100); - matrix.add(3, 22); - matrix.add(3, 75); - matrix.add(2, 99); - matrix.add(4, 0); - matrix.merge(3, 5); - - let expected = [99]; - let mut iter = expected.iter(); - for i in matrix.iter(2) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); - - let expected = [22, 75]; - let mut iter = expected.iter(); - for i in matrix.iter(3) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); - - let expected = [0]; - let mut iter = expected.iter(); - for i in matrix.iter(4) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); - - let expected = [22, 75]; - let mut iter = expected.iter(); - for i in matrix.iter(5) { - let j = *iter.next().unwrap(); - assert_eq!(i, j); - } - assert!(iter.next().is_none()); -} diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs index baac7565868..c31321fa374 100644 --- a/src/librustc_data_structures/graph/implementation/mod.rs +++ b/src/librustc_data_structures/graph/implementation/mod.rs @@ -30,7 +30,7 @@ //! the field `next_edge`). Each of those fields is an array that should //! be indexed by the direction (see the type `Direction`). -use bitvec::BitArray; +use bit_set::BitSet; use std::fmt::Debug; use std::usize; use snapshot_vec::{SnapshotVec, SnapshotVecDelegate}; @@ -266,7 +266,7 @@ pub fn nodes_in_postorder( direction: Direction, entry_node: NodeIndex, ) -> Vec { - let mut visited = BitArray::new(self.len_nodes()); + let mut visited = BitSet::new_empty(self.len_nodes()); let mut stack = vec![]; let mut result = Vec::with_capacity(self.len_nodes()); let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| { @@ -348,7 +348,7 @@ pub struct DepthFirstTraversal<'g, N, E> { graph: &'g Graph, stack: Vec, - visited: BitArray, + visited: BitSet, direction: Direction, } @@ -358,7 +358,7 @@ pub fn with_start_node( start_node: NodeIndex, direction: Direction, ) -> Self { - let mut visited = BitArray::new(graph.len_nodes()); + let mut visited = BitSet::new_empty(graph.len_nodes()); visited.insert(start_node.node_id()); DepthFirstTraversal { graph, diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs deleted file mode 100644 index 5ba8c150e1f..00000000000 --- a/src/librustc_data_structures/indexed_set.rs +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use array_vec::ArrayVec; -use std::fmt; -use std::mem; -use std::slice; -use bitvec::{bitwise, BitArray, BitIter, Intersect, Subtract, Union, Word, WORD_BITS}; -use indexed_vec::Idx; -use rustc_serialize; - -/// This is implemented by all the index sets so that IdxSet::union() can be -/// passed any type of index set. -pub trait UnionIntoIdxSet { - // Performs `other = other | self`. - fn union_into(&self, other: &mut IdxSet) -> bool; -} - -/// This is implemented by all the index sets so that IdxSet::subtract() can be -/// passed any type of index set. -pub trait SubtractFromIdxSet { - // Performs `other = other - self`. - fn subtract_from(&self, other: &mut IdxSet) -> bool; -} - -/// Represents a set of some element type E, where each E is identified by some -/// unique index type `T`. -/// -/// In other words, `T` is the type used to index into the bitvector -/// this type uses to represent the set of object it holds. -/// -/// The representation is dense, using one bit per possible element. -#[derive(Clone, Eq, PartialEq)] -pub struct IdxSet(BitArray); - -impl rustc_serialize::Encodable for IdxSet { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { - self.0.encode(encoder) - } -} - -impl rustc_serialize::Decodable for IdxSet { - fn decode(d: &mut D) -> Result, D::Error> { - Ok(IdxSet(rustc_serialize::Decodable::decode(d)?)) - } -} - -impl fmt::Debug for IdxSet { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - w.debug_list() - .entries(self.iter()) - .finish() - } -} - -impl IdxSet { - /// Creates set holding no elements. - pub fn new_empty(domain_size: usize) -> Self { - IdxSet(BitArray::new_empty(domain_size)) - } - - /// Creates set holding every element whose index falls in range 0..domain_size. - pub fn new_filled(domain_size: usize) -> Self { - IdxSet(BitArray::new_filled(domain_size)) - } - - /// Duplicates as a hybrid set. - pub fn to_hybrid(&self) -> HybridIdxSet { - // This domain_size may be slightly larger than the one specified - // upon creation, due to rounding up to a whole word. That's ok. - let domain_size = self.words().len() * WORD_BITS; - - // Note: we currently don't bother trying to make a Sparse set. - HybridIdxSet::Dense(self.to_owned(), domain_size) - } - - /// Removes all elements - pub fn clear(&mut self) { - self.0.clear(); - } - - /// Sets all elements up to `domain_size` - pub fn set_up_to(&mut self, domain_size: usize) { - self.0.set_up_to(domain_size); - } - - /// Removes `elem` from the set `self`; returns true iff this changed `self`. - pub fn remove(&mut self, elem: &T) -> bool { - self.0.remove(*elem) - } - - /// Adds `elem` to the set `self`; returns true iff this changed `self`. - pub fn add(&mut self, elem: &T) -> bool { - self.0.insert(*elem) - } - - /// Returns true iff set `self` contains `elem`. - pub fn contains(&self, elem: &T) -> bool { - self.0.contains(*elem) - } - - pub fn words(&self) -> &[Word] { - self.0.words() - } - - pub fn words_mut(&mut self) -> &mut [Word] { - self.0.words_mut() - } - - /// Efficiently overwrite `self` with `other`. Panics if `self` and `other` - /// don't have the same length. - pub fn overwrite(&mut self, other: &IdxSet) { - self.words_mut().clone_from_slice(other.words()); - } - - /// Set `self = self | other` and return true if `self` changed - /// (i.e., if new bits were added). - pub fn union(&mut self, other: &impl UnionIntoIdxSet) -> bool { - other.union_into(self) - } - - /// Set `self = self - other` and return true if `self` changed. - /// (i.e., if any bits were removed). - pub fn subtract(&mut self, other: &impl SubtractFromIdxSet) -> bool { - other.subtract_from(self) - } - - /// Set `self = self & other` and return true if `self` changed. - /// (i.e., if any bits were removed). - pub fn intersect(&mut self, other: &IdxSet) -> bool { - bitwise(self.words_mut(), other.words(), &Intersect) - } - - pub fn iter(&self) -> BitIter { - self.0.iter() - } -} - -impl UnionIntoIdxSet for IdxSet { - fn union_into(&self, other: &mut IdxSet) -> bool { - bitwise(other.words_mut(), self.words(), &Union) - } -} - -impl SubtractFromIdxSet for IdxSet { - fn subtract_from(&self, other: &mut IdxSet) -> bool { - bitwise(other.words_mut(), self.words(), &Subtract) - } -} - -const SPARSE_MAX: usize = 8; - -/// A sparse index set with a maximum of SPARSE_MAX elements. Used by -/// HybridIdxSet; do not use directly. -/// -/// The elements are stored as an unsorted vector with no duplicates. -#[derive(Clone, Debug)] -pub struct SparseIdxSet(ArrayVec<[T; SPARSE_MAX]>); - -impl SparseIdxSet { - fn new() -> Self { - SparseIdxSet(ArrayVec::new()) - } - - fn len(&self) -> usize { - self.0.len() - } - - fn contains(&self, elem: &T) -> bool { - self.0.contains(elem) - } - - fn add(&mut self, elem: &T) -> bool { - // Ensure there are no duplicates. - if self.0.contains(elem) { - false - } else { - self.0.push(*elem); - true - } - } - - fn remove(&mut self, elem: &T) -> bool { - if let Some(i) = self.0.iter().position(|e| e == elem) { - // Swap the found element to the end, then pop it. - let len = self.0.len(); - self.0.swap(i, len - 1); - self.0.pop(); - true - } else { - false - } - } - - fn to_dense(&self, domain_size: usize) -> IdxSet { - let mut dense = IdxSet::new_empty(domain_size); - for elem in self.0.iter() { - dense.add(elem); - } - dense - } - - fn iter(&self) -> slice::Iter { - self.0.iter() - } -} - -impl UnionIntoIdxSet for SparseIdxSet { - fn union_into(&self, other: &mut IdxSet) -> bool { - let mut changed = false; - for elem in self.iter() { - changed |= other.add(&elem); - } - changed - } -} - -impl SubtractFromIdxSet for SparseIdxSet { - fn subtract_from(&self, other: &mut IdxSet) -> bool { - let mut changed = false; - for elem in self.iter() { - changed |= other.remove(&elem); - } - changed - } -} - -/// Like IdxSet, but with a hybrid representation: sparse when there are few -/// elements in the set, but dense when there are many. It's especially -/// efficient for sets that typically have a small number of elements, but a -/// large `domain_size`, and are cleared frequently. -#[derive(Clone, Debug)] -pub enum HybridIdxSet { - Sparse(SparseIdxSet, usize), - Dense(IdxSet, usize), -} - -impl HybridIdxSet { - pub fn new_empty(domain_size: usize) -> Self { - HybridIdxSet::Sparse(SparseIdxSet::new(), domain_size) - } - - pub fn clear(&mut self) { - let domain_size = match *self { - HybridIdxSet::Sparse(_, size) => size, - HybridIdxSet::Dense(_, size) => size, - }; - *self = HybridIdxSet::new_empty(domain_size); - } - - /// Returns true iff set `self` contains `elem`. - pub fn contains(&self, elem: &T) -> bool { - match self { - HybridIdxSet::Sparse(sparse, _) => sparse.contains(elem), - HybridIdxSet::Dense(dense, _) => dense.contains(elem), - } - } - - /// Adds `elem` to the set `self`. - pub fn add(&mut self, elem: &T) -> bool { - match self { - HybridIdxSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => { - // The set is sparse and has space for `elem`. - sparse.add(elem) - } - HybridIdxSet::Sparse(sparse, _) if sparse.contains(elem) => { - // The set is sparse and does not have space for `elem`, but - // that doesn't matter because `elem` is already present. - false - } - HybridIdxSet::Sparse(_, _) => { - // The set is sparse and full. Convert to a dense set. - // - // FIXME: This code is awful, but I can't work out how else to - // appease the borrow checker. - let dummy = HybridIdxSet::Sparse(SparseIdxSet::new(), 0); - match mem::replace(self, dummy) { - HybridIdxSet::Sparse(sparse, domain_size) => { - let mut dense = sparse.to_dense(domain_size); - let changed = dense.add(elem); - assert!(changed); - mem::replace(self, HybridIdxSet::Dense(dense, domain_size)); - changed - } - _ => panic!("impossible"), - } - } - - HybridIdxSet::Dense(dense, _) => dense.add(elem), - } - } - - /// Removes `elem` from the set `self`. - pub fn remove(&mut self, elem: &T) -> bool { - // Note: we currently don't bother going from Dense back to Sparse. - match self { - HybridIdxSet::Sparse(sparse, _) => sparse.remove(elem), - HybridIdxSet::Dense(dense, _) => dense.remove(elem), - } - } - - /// Converts to a dense set, consuming itself in the process. - pub fn to_dense(self) -> IdxSet { - match self { - HybridIdxSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size), - HybridIdxSet::Dense(dense, _) => dense, - } - } - - /// Iteration order is unspecified. - pub fn iter(&self) -> HybridIter { - match self { - HybridIdxSet::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()), - HybridIdxSet::Dense(dense, _) => HybridIter::Dense(dense.iter()), - } - } -} - -impl UnionIntoIdxSet for HybridIdxSet { - fn union_into(&self, other: &mut IdxSet) -> bool { - match self { - HybridIdxSet::Sparse(sparse, _) => sparse.union_into(other), - HybridIdxSet::Dense(dense, _) => dense.union_into(other), - } - } -} - -impl SubtractFromIdxSet for HybridIdxSet { - fn subtract_from(&self, other: &mut IdxSet) -> bool { - match self { - HybridIdxSet::Sparse(sparse, _) => sparse.subtract_from(other), - HybridIdxSet::Dense(dense, _) => dense.subtract_from(other), - } - } -} - -pub enum HybridIter<'a, T: Idx> { - Sparse(slice::Iter<'a, T>), - Dense(BitIter<'a, T>), -} - -impl<'a, T: Idx> Iterator for HybridIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - match self { - HybridIter::Sparse(sparse) => sparse.next().map(|e| *e), - HybridIter::Dense(dense) => dense.next(), - } - } -} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 9435cb31842..70b960ac351 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -60,14 +60,12 @@ pub use rustc_serialize::hex::ToHex; pub mod svh; -pub mod array_vec; pub mod base_n; -pub mod bitvec; +pub mod bit_set; pub mod const_cstr; pub mod flock; pub mod fx; pub mod graph; -pub mod indexed_set; pub mod indexed_vec; pub mod obligation_forest; pub mod owning_ref; diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 215c44dec69..c85d771a181 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -457,7 +457,7 @@ fn hash_stable(&self, } -impl HashStable for ::indexed_set::IdxSet +impl HashStable for ::bit_set::BitSet { fn hash_stable(&self, ctx: &mut CTX, diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index 2acc29acb0c..1512b30eead 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use bitvec::BitMatrix; +use bit_set::BitMatrix; use fx::FxHashMap; use sync::Lock; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; @@ -279,7 +279,7 @@ pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> { // // This same algorithm is used in `parents` below. - let mut candidates = closure.intersection(a.0, b.0); // (1) + let mut candidates = closure.intersect_rows(a.0, b.0); // (1) pare_down(&mut candidates, closure); // (2) candidates.reverse(); // (3a) pare_down(&mut candidates, closure); // (3b) @@ -321,7 +321,7 @@ pub fn parents(&self, a: &T) -> Vec<&T> { // with a slight tweak. In the case where `a R a`, we remove // that from the set of candidates. let ancestors = self.with_closure(|closure| { - let mut ancestors = closure.intersection(a.0, a.0); + let mut ancestors = closure.intersect_rows(a.0, a.0); // Remove anything that can reach `a`. If this is a // reflexive relation, this will include `a` itself. @@ -366,10 +366,10 @@ fn compute_closure(&self) -> BitMatrix { changed = false; for edge in &self.edges { // add an edge from S -> T - changed |= matrix.add(edge.source.0, edge.target.0); + changed |= matrix.insert(edge.source.0, edge.target.0); // add all outgoing edges from T into S - changed |= matrix.merge(edge.target.0, edge.source.0); + changed |= matrix.union_rows(edge.target.0, edge.source.0); } } matrix diff --git a/src/librustc_data_structures/work_queue.rs b/src/librustc_data_structures/work_queue.rs index 0c8ec753a18..af9ed9306eb 100644 --- a/src/librustc_data_structures/work_queue.rs +++ b/src/librustc_data_structures/work_queue.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use indexed_set::IdxSet; +use bit_set::BitSet; use indexed_vec::Idx; use std::collections::VecDeque; @@ -20,7 +20,7 @@ /// and also use a bit set to track occupancy. pub struct WorkQueue { deque: VecDeque, - set: IdxSet, + set: BitSet, } impl WorkQueue { @@ -29,7 +29,7 @@ impl WorkQueue { pub fn with_all(len: usize) -> Self { WorkQueue { deque: (0..len).map(T::new).collect(), - set: IdxSet::new_filled(len), + set: BitSet::new_filled(len), } } @@ -38,14 +38,14 @@ pub fn with_all(len: usize) -> Self { pub fn with_none(len: usize) -> Self { WorkQueue { deque: VecDeque::with_capacity(len), - set: IdxSet::new_empty(len), + set: BitSet::new_empty(len), } } /// Attempt to enqueue `element` in the work queue. Returns false if it was already present. #[inline] pub fn insert(&mut self, element: T) -> bool { - if self.set.add(&element) { + if self.set.insert(element) { self.deque.push_back(element); true } else { @@ -57,7 +57,7 @@ pub fn insert(&mut self, element: T) -> bool { #[inline] pub fn pop(&mut self) -> Option { if let Some(element) = self.deque.pop_front() { - self.set.remove(&element); + self.set.remove(element); Some(element) } else { None diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index ff35371976a..0a7bd3d9702 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -198,7 +198,7 @@ pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { pub fn create_region_hierarchy(&mut self, rh: &RH, parent: (region::Scope, region::ScopeDepth)) { - let me = region::Scope::Node(rh.id); + let me = region::Scope { id: rh.id, data: region::ScopeData::Node }; self.region_scope_tree.record_scope_parent(me, Some(parent)); for child_rh in rh.sub { self.create_region_hierarchy(child_rh, (me, parent.1 + 1)); @@ -209,7 +209,10 @@ pub fn create_simple_region_hierarchy(&mut self) { // creates a region hierarchy where 1 is root, 10 and 11 are // children of 1, etc - let dscope = region::Scope::Destruction(hir::ItemLocalId(1)); + let dscope = region::Scope { + id: hir::ItemLocalId(1), + data: region::ScopeData::Destruction + }; self.region_scope_tree.record_scope_parent(dscope, None); self.create_region_hierarchy(&RH { id: hir::ItemLocalId(1), @@ -355,7 +358,10 @@ pub fn t_rptr_late_bound_with_debruijn(&self, } pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> { - let r = ty::ReScope(region::Scope::Node(hir::ItemLocalId(id))); + let r = ty::ReScope(region::Scope { + id: hir::ItemLocalId(id), + data: region::ScopeData::Node + }); self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 101ca0650c8..b24f8ddf4d9 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -9,6 +9,7 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] +log = "0.4" serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 825e31539c8..2799f2cc81f 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -232,6 +232,7 @@ pub fn span_help>(&mut self, /// inline it will only show the text message and not the text. /// /// See `CodeSuggestion` for more information. + #[deprecated(note = "Use `span_suggestion_short_with_applicability`")] pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { @@ -263,6 +264,7 @@ pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) /// * may contain a name of a function, variable or type, but not whole expressions /// /// See `CodeSuggestion` for more information. + #[deprecated(note = "Use `span_suggestion_with_applicability`")] pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { @@ -278,10 +280,11 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &m self } - pub fn multipart_suggestion( + pub fn multipart_suggestion_with_applicability( &mut self, msg: &str, suggestion: Vec<(Span, String)>, + applicability: Applicability, ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { @@ -292,12 +295,26 @@ pub fn multipart_suggestion( }], msg: msg.to_owned(), show_code_when_inline: true, - applicability: Applicability::Unspecified, + applicability, }); self } + #[deprecated(note = "Use `multipart_suggestion_with_applicability`")] + pub fn multipart_suggestion( + &mut self, + msg: &str, + suggestion: Vec<(Span, String)>, + ) -> &mut Self { + self.multipart_suggestion_with_applicability( + msg, + suggestion, + Applicability::Unspecified, + ) + } + /// Prints out a message with multiple suggested edits of the code. + #[deprecated(note = "Use `span_suggestions_with_applicability`")] pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: suggestions.into_iter().map(|snippet| Substitution { diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 1b34898b990..60a68b1e496 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -21,6 +21,10 @@ use syntax_pos::{MultiSpan, Span}; /// Used for emitting structured error messages and other diagnostic information. +/// +/// If there is some state in a downstream crate you would like to +/// access in the methods of `DiagnosticBuilder` here, consider +/// extending `HandlerFlags`, accessed via `self.handler.flags`. #[must_use] #[derive(Clone)] pub struct DiagnosticBuilder<'a> { @@ -39,16 +43,18 @@ pub struct DiagnosticBuilder<'a> { /// it easy to declare such methods on the builder. macro_rules! forward { // Forward pattern for &self -> &Self - (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => { + (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => { pub fn $n(&self, $($name: $ty),*) -> &Self { + #[allow(deprecated)] self.diagnostic.$n($($name),*); self } }; // Forward pattern for &mut self -> &mut Self - (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => { + (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => { pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { + #[allow(deprecated)] self.diagnostic.$n($($name),*); self } @@ -56,8 +62,12 @@ pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { // Forward pattern for &mut self -> &mut Self, with S: Into // type parameter. No obvious way to make this more generic. - (pub fn $n:ident>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => { + (pub fn $n:ident>( + &mut self, + $($name:ident: $ty:ty),* + $(,)*) -> &mut Self) => { pub fn $n>(&mut self, $($name: $ty),*) -> &mut Self { + #[allow(deprecated)] self.diagnostic.$n($($name),*); self } @@ -89,8 +99,14 @@ pub fn emit(&mut self) { self.cancel(); } - /// Buffers the diagnostic for later emission. - pub fn buffer(self, buffered_diagnostics: &mut Vec) { + /// Buffers the diagnostic for later emission, unless handler + /// has disabled such buffering. + pub fn buffer(mut self, buffered_diagnostics: &mut Vec) { + if self.handler.flags.dont_buffer_diagnostics || self.handler.flags.treat_err_as_bug { + self.emit(); + return; + } + // We need to use `ptr::read` because `DiagnosticBuilder` // implements `Drop`. let diagnostic; @@ -98,6 +114,9 @@ pub fn buffer(self, buffered_diagnostics: &mut Vec) { diagnostic = ::std::ptr::read(&self.diagnostic); ::std::mem::forget(self); }; + // Logging here is useful to help track down where in logs an error was + // actually emitted. + debug!("buffer: diagnostic={:?}", diagnostic); buffered_diagnostics.push(diagnostic); } @@ -144,49 +163,75 @@ pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self forward!(pub fn note_expected_found(&mut self, label: &dyn fmt::Display, expected: DiagnosticStyledString, - found: DiagnosticStyledString) - -> &mut Self); + found: DiagnosticStyledString, + ) -> &mut Self); forward!(pub fn note_expected_found_extra(&mut self, label: &dyn fmt::Display, expected: DiagnosticStyledString, found: DiagnosticStyledString, expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display) - -> &mut Self); + found_extra: &dyn fmt::Display, + ) -> &mut Self); forward!(pub fn note(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_note>(&mut self, sp: S, - msg: &str) - -> &mut Self); + msg: &str, + ) -> &mut Self); forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self); forward!(pub fn help(&mut self , msg: &str) -> &mut Self); forward!(pub fn span_help>(&mut self, sp: S, - msg: &str) - -> &mut Self); - forward!(pub fn span_suggestion_short(&mut self, - sp: Span, - msg: &str, - suggestion: String) - -> &mut Self); + msg: &str, + ) -> &mut Self); + + #[deprecated(note = "Use `span_suggestion_short_with_applicability`")] + forward!(pub fn span_suggestion_short( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + ) -> &mut Self); + + #[deprecated(note = "Use `multipart_suggestion_with_applicability`")] forward!(pub fn multipart_suggestion( &mut self, msg: &str, - suggestion: Vec<(Span, String)> + suggestion: Vec<(Span, String)>, ) -> &mut Self); + + #[deprecated(note = "Use `span_suggestion_with_applicability`")] forward!(pub fn span_suggestion(&mut self, sp: Span, msg: &str, - suggestion: String) - -> &mut Self); + suggestion: String, + ) -> &mut Self); + + #[deprecated(note = "Use `span_suggestions_with_applicability`")] forward!(pub fn span_suggestions(&mut self, sp: Span, msg: &str, - suggestions: Vec) - -> &mut Self); + suggestions: Vec, + ) -> &mut Self); + + pub fn multipart_suggestion_with_applicability(&mut self, + msg: &str, + suggestion: Vec<(Span, String)>, + applicability: Applicability, + ) -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.multipart_suggestion_with_applicability( + msg, + suggestion, + applicability, + ); + self + } + pub fn span_suggestion_with_applicability(&mut self, sp: Span, msg: &str, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3582c2359c8..266aa326981 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -23,6 +23,8 @@ extern crate termcolor; #[cfg(unix)] extern crate libc; +#[macro_use] +extern crate log; extern crate rustc_data_structures; extern crate serialize as rustc_serialize; extern crate syntax_pos; @@ -303,9 +305,20 @@ fn default_track_diagnostic(_: &Diagnostic) {} #[derive(Default)] pub struct HandlerFlags { + /// If false, warning-level lints are suppressed. + /// (rustc: see `--allow warnings` and `--cap-lints`) pub can_emit_warnings: bool, + /// If true, error-level diagnostics are upgraded to bug-level. + /// (rustc: see `-Z treat-err-as-bug`) pub treat_err_as_bug: bool, + /// If true, immediately emit diagnostics that would otherwise be buffered. + /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`) + pub dont_buffer_diagnostics: bool, + /// If true, immediately print bugs registered with `delay_span_bug`. + /// (rustc: see `-Z report-delayed-bugs`) pub report_delayed_bugs: bool, + /// show macro backtraces even for non-local macros. + /// (rustc: see `-Z external-macro-backtrace`) pub external_macro_backtrace: bool, } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index b662b825013..f9e717f8d45 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -783,7 +783,7 @@ impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) { for &&(n, _, ref g) in &self.depr_attrs { if attr.name() == n { - if let &AttributeGate::Gated(Stability::Deprecated(link), + if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion), ref name, ref reason, _) = g { @@ -792,7 +792,7 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) { let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg); err.span_suggestion_short_with_applicability( attr.span, - "remove this attribute", + suggestion.unwrap_or("remove this attribute"), String::new(), Applicability::MachineApplicable ); diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 09871c0e840..56d204f15d9 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -59,10 +59,10 @@ fn char_has_case(c: char) -> bool { fn is_camel_case(name: ast::Name) -> bool { let name = name.as_str(); + let name = name.trim_matches('_'); if name.is_empty() { return true; } - let name = name.trim_matches('_'); // start with a non-lowercase letter rather than non-uppercase // ones (some scripts don't have a concept of upper/lowercase) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5eb54195215..6eef2397f9c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -100,6 +100,18 @@ enum LoadResult { Loaded(Library), } +enum LoadError<'a> { + LocatorError(locator::Context<'a>), +} + +impl<'a> LoadError<'a> { + fn report(self) -> ! { + match self { + LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(), + } + } +} + impl<'a> CrateLoader<'a> { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { CrateLoader { @@ -132,7 +144,8 @@ fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind) // from the strings on the command line. let source = &self.cstore.get_crate_data(cnum).source; if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { - let found = locs.iter().any(|l| { + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + let found = locs.iter().filter_map(|l| l.as_ref()).any(|l| { let l = fs::canonicalize(l).ok(); source.dylib.as_ref().map(|p| &p.0) == l.as_ref() || source.rlib.as_ref().map(|p| &p.0) == l.as_ref() @@ -267,16 +280,17 @@ fn register_crate(&mut self, (cnum, cmeta) } - fn resolve_crate(&mut self, - root: &Option, - ident: Symbol, - name: Symbol, - hash: Option<&Svh>, - extra_filename: Option<&str>, - span: Span, - path_kind: PathKind, - mut dep_kind: DepKind) - -> (CrateNum, Lrc) { + fn resolve_crate<'b>( + &'b mut self, + root: &'b Option, + ident: Symbol, + name: Symbol, + hash: Option<&'b Svh>, + extra_filename: Option<&'b str>, + span: Span, + path_kind: PathKind, + mut dep_kind: DepKind, + ) -> Result<(CrateNum, Lrc), LoadError<'b>> { info!("resolving crate `extern crate {} as {}`", name, ident); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { LoadResult::Previous(cnum) @@ -320,7 +334,7 @@ fn resolve_crate(&mut self, }; self.load(&mut proc_macro_locator) - }).unwrap_or_else(|| locate_ctxt.report_errs()) + }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))? }; match result { @@ -332,10 +346,10 @@ fn resolve_crate(&mut self, data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - (cnum, data) + Ok((cnum, data)) } LoadResult::Loaded(library) => { - self.register_crate(root, ident, span, library, dep_kind) + Ok(self.register_crate(root, ident, span, library, dep_kind)) } } } @@ -440,7 +454,7 @@ fn resolve_crate_deps(&mut self, let (local_cnum, ..) = self.resolve_crate( root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, PathKind::Dependency, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); local_cnum })).collect() } @@ -694,7 +708,8 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) { let dep_kind = DepKind::Implicit; let (cnum, data) = - self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -802,7 +817,8 @@ fn inject_sanitizer_runtime(&mut self) { let dep_kind = DepKind::Explicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, - PathKind::Crate, dep_kind); + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime if !data.root.sanitizer_runtime { @@ -825,7 +841,8 @@ fn inject_profiler_runtime(&mut self) { let dep_kind = DepKind::Implicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, - PathKind::Crate, dep_kind); + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.root.profiler_runtime { @@ -945,7 +962,8 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) { None, DUMMY_SP, PathKind::Crate, - DepKind::Implicit); + DepKind::Implicit) + .unwrap_or_else(|err| err.report()); self.sess.injected_allocator.set(Some(cnum)); data }) @@ -1102,7 +1120,7 @@ pub fn process_extern_crate( let (cnum, ..) = self.resolve_crate( &None, item.ident.name, orig_name, None, None, item.span, PathKind::Crate, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -1130,7 +1148,7 @@ pub fn process_path_extern( ) -> CrateNum { let cnum = self.resolve_crate( &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit - ).0; + ).unwrap_or_else(|err| err.report()).0; self.update_extern_crate( cnum, @@ -1146,4 +1164,28 @@ pub fn process_path_extern( cnum } + + pub fn maybe_process_path_extern( + &mut self, + name: Symbol, + span: Span, + ) -> Option { + let cnum = self.resolve_crate( + &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit + ).ok()?.0; + + self.update_extern_crate( + cnum, + ExternCrate { + src: ExternCrateSource::Path, + span, + // to have the least priority in `update_extern_crate` + path_len: usize::max_value(), + direct: true, + }, + &mut FxHashSet(), + ); + + Some(cnum) + } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 4382a3c12c9..23f941f744b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -42,7 +42,7 @@ use syntax::parse::source_file_to_stream; use syntax::symbol::Symbol; use syntax_pos::{Span, NO_EXPANSION, FileName}; -use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::bit_set::BitSet; use rustc::hir; macro_rules! provide { @@ -141,7 +141,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) } mir } mir_const_qualif => { - (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSet::new_empty(0))) + (cdata.mir_const_qualif(def_id.index), Lrc::new(BitSet::new_empty(0))) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 9492385957e..adff34af61e 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -438,7 +438,12 @@ fn find_library_crate(&mut self, if self.hash.is_none() { self.should_match_name = false; if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { - return self.find_commandline_library(s.iter()); + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + if s.iter().any(|l| l.is_some()) { + return self.find_commandline_library( + s.iter().filter_map(|l| l.as_ref()), + ); + } } self.should_match_name = true; } @@ -617,7 +622,7 @@ fn extract_one(&mut self, } } Err(err) => { - info!("no metadata found: {}", err); + warn!("no metadata found: {}", err); continue; } }; diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 8ddcfa05432..bb70b4b76c2 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -17,7 +17,7 @@ use rustc::ty::{Region, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use std::fmt; use std::hash::Hash; use std::ops::Index; @@ -102,7 +102,7 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { crate enum LocalsStateAtExit { AllAreInvalidated, - SomeAreInvalidated { has_storage_dead_or_moved: BitArray } + SomeAreInvalidated { has_storage_dead_or_moved: BitSet } } impl LocalsStateAtExit { @@ -111,7 +111,7 @@ fn build( mir: &Mir<'tcx>, move_data: &MoveData<'tcx> ) -> Self { - struct HasStorageDead(BitArray); + struct HasStorageDead(BitSet); impl<'tcx> Visitor<'tcx> for HasStorageDead { fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { @@ -124,7 +124,7 @@ fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { if locals_are_invalidated_at_exit { LocalsStateAtExit::AllAreInvalidated } else { - let mut has_storage_dead = HasStorageDead(BitArray::new(mir.local_decls.len())); + let mut has_storage_dead = HasStorageDead(BitSet::new_empty(mir.local_decls.len())); has_storage_dead.visit_mir(mir); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 977b6a71f5e..9187cb97e69 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -17,7 +17,7 @@ use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; use super::borrow_set::BorrowData; @@ -38,6 +38,12 @@ pub(super) fn report_use_of_moved_or_uninitialized( (place, span): (&Place<'tcx>, Span), mpi: MovePathIndex, ) { + debug!( + "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \ + span={:?} mpi={:?}", + context, desired_action, place, span, mpi + ); + let use_spans = self .move_spans(place, context.loc) .or_else(|| self.borrow_spans(span, context.loc)); @@ -49,7 +55,7 @@ pub(super) fn report_use_of_moved_or_uninitialized( if mois.is_empty() { let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); - if self.moved_error_reported.contains(&root_place.clone()) { + if self.uninitialized_error_reported.contains(&root_place.clone()) { debug!( "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", root_place @@ -57,7 +63,7 @@ pub(super) fn report_use_of_moved_or_uninitialized( return; } - self.moved_error_reported.insert(root_place.clone()); + self.uninitialized_error_reported.insert(root_place.clone()); let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) { Some(name) => format!("`{}`", name), @@ -80,6 +86,14 @@ pub(super) fn report_use_of_moved_or_uninitialized( err.buffer(&mut self.errors_buffer); } else { + if let Some((reported_place, _)) = self.move_error_reported.get(&mois) { + if self.prefixes(&reported_place, PrefixSet::All).any(|p| p == place) { + debug!("report_use_of_moved_or_uninitialized place: error suppressed \ + mois={:?}", mois); + return; + } + } + let msg = ""; //FIXME: add "partially " or "collaterally " let mut err = self.tcx.cannot_act_on_moved_value( @@ -167,7 +181,13 @@ pub(super) fn report_use_of_moved_or_uninitialized( } } - err.buffer(&mut self.errors_buffer); + if let Some((_, mut old_err)) = self.move_error_reported.insert( + mois, + (place.clone(), err) + ) { + // Cancel the old error so it doesn't ICE. + old_err.cancel(); + } } } @@ -564,9 +584,20 @@ fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec( _ => Some(tcx.hir.body_owned_by(id)), }; - let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, mir, @@ -177,24 +179,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); - let flow_uninits = FlowAtLocation::new(do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, mir, &mdpe), - |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), - )); - let flow_ever_inits = FlowAtLocation::new(do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - EverInitializedPlaces::new(tcx, mir, &mdpe), - |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), - )); let locals_are_invalidated_at_exit = match tcx.hir.body_owner_kind(id) { hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, @@ -216,6 +200,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( &borrow_set, &mut errors_buffer, ); + + // The various `flow_*` structures can be large. We drop `flow_inits` here + // so it doesn't overlap with the others below. This reduces peak memory + // usage significantly on some benchmarks. + drop(flow_inits); + let regioncx = Rc::new(regioncx); let flow_borrows = FlowAtLocation::new(do_dataflow( @@ -227,6 +217,24 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); + let flow_uninits = FlowAtLocation::new(do_dataflow( + tcx, + mir, + id, + &attributes, + &dead_unwinds, + MaybeUninitializedPlaces::new(tcx, mir, &mdpe), + |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), + )); + let flow_ever_inits = FlowAtLocation::new(do_dataflow( + tcx, + mir, + id, + &attributes, + &dead_unwinds, + EverInitializedPlaces::new(tcx, mir, &mdpe), + |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), + )); let movable_generator = match tcx.hir.get(id) { Node::Expr(&hir::Expr { @@ -249,7 +257,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( locals_are_invalidated_at_exit, access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), - moved_error_reported: FxHashSet(), + move_error_reported: BTreeMap::new(), + uninitialized_error_reported: FxHashSet(), errors_buffer, nonlexical_regioncx: regioncx, used_mut: FxHashSet(), @@ -327,6 +336,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } } + // Buffer any move errors that we collected and de-duplicated. + for (_, (_, diag)) in mbcx.move_error_reported { + diag.buffer(&mut mbcx.errors_buffer); + } + if mbcx.errors_buffer.len() > 0 { mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); @@ -402,9 +416,24 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// but it is currently inconvenient to track down the BorrowIndex /// at the time we detect and report a reservation error. reservation_error_reported: FxHashSet>, - /// This field keeps track of errors reported in the checking of moved variables, + /// This field keeps track of move errors that are to be reported for given move indicies. + /// + /// There are situations where many errors can be reported for a single move out (see #53807) + /// and we want only the best of those errors. + /// + /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the + /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the + /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once + /// all move errors have been reported, any diagnostics in this map are added to the buffer + /// to be emitted. + /// + /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary + /// when errors in the map are being re-added to the error buffer so that errors with the + /// same primary span come out in a consistent order. + move_error_reported: BTreeMap, (Place<'tcx>, DiagnosticBuilder<'cx>)>, + /// This field keeps track of errors reported in the checking of uninitialized variables, /// so that we don't report seemingly duplicate errors. - moved_error_reported: FxHashSet>, + uninitialized_error_reported: FxHashSet>, /// Errors to be reported buffer errors_buffer: Vec, /// This field keeps track of all the local variables that are declared mut and are mutated. @@ -795,7 +824,7 @@ enum LocalMutationIsAllowed { No, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] enum InitializationRequiringAction { Update, Borrow, @@ -1589,7 +1618,7 @@ fn check_if_reassignment_to_immutable_state( // Check if any of the initializiations of `local` have happened yet: let mpi = self.move_data.rev_lookup.find_local(local); let init_indices = &self.move_data.init_path_map[mpi]; - let first_init_index = init_indices.iter().find(|ii| flow_state.ever_inits.contains(ii)); + let first_init_index = init_indices.iter().find(|&ii| flow_state.ever_inits.contains(*ii)); if let Some(&init_index) = first_init_index { // And, if so, report an error. let init = &self.move_data.inits[init_index]; @@ -1647,7 +1676,7 @@ fn check_if_full_path_is_moved( debug!("check_if_full_path_is_moved place: {:?}", place_span.0); match self.move_path_closest_to(place_span.0) { Ok(mpi) => { - if maybe_uninits.contains(&mpi) { + if maybe_uninits.contains(mpi) { self.report_use_of_moved_or_uninitialized( context, desired_action, @@ -1963,7 +1992,7 @@ fn add_used_mut<'d>( // keyword, since the mutation may be a possible reassignment. let mpi = self.move_data.rev_lookup.find_local(*local); let ii = &self.move_data.init_path_map[mpi]; - for index in ii { + for &index in ii { if flow_state.ever_inits.contains(index) { self.used_mut.insert(*local); break; diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 290c7032388..52d051ebe7b 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -11,7 +11,7 @@ use core::unicode::property::Pattern_White_Space; use rustc::mir::*; use rustc::ty; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::{DiagnosticBuilder,Applicability}; use syntax_pos::Span; use borrow_check::MirBorrowckCtxt; @@ -350,16 +350,18 @@ fn add_move_hints( // expressions `a[b]`, which roughly desugar to // `*Index::index(&a, b)` or // `*IndexMut::index_mut(&mut a, b)`. - err.span_suggestion( + err.span_suggestion_with_applicability( span, "consider removing the `*`", snippet[1..].to_owned(), + Applicability::Unspecified, ); } else { - err.span_suggestion( + err.span_suggestion_with_applicability( span, "consider borrowing here", format!("&{}", snippet), + Applicability::Unspecified, ); } @@ -420,10 +422,11 @@ fn add_move_error_suggestions( suggestions.sort_unstable_by_key(|&(span, _, _)| span); suggestions.dedup_by_key(|&mut (span, _, _)| span); for (span, to_remove, suggestion) in suggestions { - err.span_suggestion( + err.span_suggestion_with_applicability( span, &format!("consider removing the `{}`", to_remove), - suggestion + suggestion, + Applicability::MachineApplicable, ); } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 78ab772d9ad..a078aa59a7d 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -22,6 +22,7 @@ use util::borrowck_errors::{BorrowckErrors, Origin}; use util::collect_writes::FindAssignments; use util::suggest_ref_mut; +use rustc_errors::Applicability; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(super) enum AccessKind { @@ -227,10 +228,11 @@ pub(super) fn report_mutability_error( assert_eq!(local_decl.mutability, Mutability::Not); err.span_label(span, format!("cannot {ACT}", ACT = act)); - err.span_suggestion( + err.span_suggestion_with_applicability( local_decl.source_info.span, "consider changing this to be mutable", format!("mut {}", local_decl.name.unwrap()), + Applicability::MachineApplicable, ); } @@ -257,10 +259,11 @@ pub(super) fn report_mutability_error( _, ) = pat.node { - err.span_suggestion( + err.span_suggestion_with_applicability( upvar_ident.span, "consider changing this to be mutable", format!("mut {}", upvar_ident.name), + Applicability::MachineApplicable, ); } } @@ -351,10 +354,11 @@ pub(super) fn report_mutability_error( }; if let Some((err_help_span, suggested_code)) = suggestion { - err.span_suggestion( + err.span_suggestion_with_applicability( err_help_span, &format!("consider changing this to be a mutable {}", pointer_desc), suggested_code, + Applicability::MachineApplicable, ); } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 0b9b9b33b3f..dfed41cb1de 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -15,16 +15,19 @@ use rustc::infer::error_reporting::nice_region_error::NiceRegionError; use rustc::infer::InferCtxt; use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind}; -use rustc::ty::{TyCtxt, RegionVid}; +use rustc::ty::{self, TyCtxt, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_errors::Diagnostic; +use rustc_errors::{Diagnostic, DiagnosticBuilder}; use std::collections::VecDeque; use std::fmt; +use syntax::symbol::keywords; use syntax_pos::Span; mod region_name; mod var_name; +use self::region_name::RegionName; + /// Constraints that are considered interesting can be categorized to /// determine why they are interesting. Order of variants indicates /// sort order of the category, thereby influencing diagnostic output. @@ -356,9 +359,9 @@ pub(super) fn report_error( self.universal_regions.is_local_free_region(fr), self.universal_regions.is_local_free_region(outlived_fr), ); + debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}", fr_is_local, outlived_fr_is_local, category); - match (category, fr_is_local, outlived_fr_is_local) { (ConstraintCategory::Assignment, true, false) | (ConstraintCategory::CallArgument, true, false) => @@ -465,9 +468,93 @@ fn report_general_error( }, } + self.add_static_impl_trait_suggestion( + infcx, &mut diag, fr, fr_name, outlived_fr, + ); + diag.buffer(errors_buffer); } + fn add_static_impl_trait_suggestion( + &self, + infcx: &InferCtxt<'_, '_, 'tcx>, + diag: &mut DiagnosticBuilder<'_>, + fr: RegionVid, + // We need to pass `fr_name` - computing it again will label it twice. + fr_name: RegionName, + outlived_fr: RegionVid, + ) { + if let ( + Some(f), + Some(ty::RegionKind::ReStatic) + ) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { + if let Some(ty::TyS { + sty: ty::TyKind::Opaque(did, substs), + .. + }) = infcx.tcx.is_suitable_region(f) + .map(|r| r.def_id) + .map(|id| infcx.tcx.return_type_impl_trait(id)) + .unwrap_or(None) + { + // Check whether or not the impl trait return type is intended to capture + // data with the static lifetime. + // + // eg. check for `impl Trait + 'static` instead of `impl Trait`. + let has_static_predicate = { + let predicates_of = infcx.tcx.predicates_of(*did); + let bounds = predicates_of.instantiate(infcx.tcx, substs); + + let mut found = false; + for predicate in bounds.predicates { + if let ty::Predicate::TypeOutlives(binder) = predicate { + if let ty::OutlivesPredicate( + _, + ty::RegionKind::ReStatic + ) = binder.skip_binder() { + found = true; + break; + } + } + } + + found + }; + + debug!("add_static_impl_trait_suggestion: has_static_predicate={:?}", + has_static_predicate); + let static_str = keywords::StaticLifetime.name(); + // If there is a static predicate, then the only sensible suggestion is to replace + // fr with `'static`. + if has_static_predicate { + diag.help( + &format!( + "consider replacing `{}` with `{}`", + fr_name, static_str, + ), + ); + } else { + // Otherwise, we should suggest adding a constraint on the return type. + let span = infcx.tcx.def_span(*did); + if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) { + let suggestable_fr_name = match fr_name { + RegionName::Named(name) => format!("{}", name), + RegionName::Synthesized(_) => "'_".to_string(), + }; + diag.span_suggestion( + span, + &format!( + "to allow this impl Trait to capture borrowed data with lifetime \ + `{}`, add `{}` as a constraint", + fr_name, suggestable_fr_name, + ), + format!("{} + {}", snippet, suggestable_fr_name), + ); + } + } + } + } + } + // Finds some region R such that `fr1: R` and `R` is live at // `elem`. crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 5ae123bdc18..857f1dae7ab 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::fmt::{self, Display}; use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::universal_regions::DefiningTy; use borrow_check::nll::ToRegionVid; @@ -21,8 +22,35 @@ use rustc_errors::DiagnosticBuilder; use syntax::ast::{Name, DUMMY_NODE_ID}; use syntax::symbol::keywords; +use syntax_pos::Span; use syntax_pos::symbol::InternedString; +/// Name of a region used in error reporting. Variants denote the source of the region name - +/// whether it was synthesized for the error message and therefore should not be used in +/// suggestions; or whether it was found from the region. +#[derive(Debug)] +pub(crate) enum RegionName { + Named(InternedString), + Synthesized(InternedString), +} + +impl RegionName { + fn as_interned_string(&self) -> &InternedString { + match self { + RegionName::Named(name) | RegionName::Synthesized(name) => name, + } + } +} + +impl Display for RegionName { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + RegionName::Named(name) | RegionName::Synthesized(name) => + write!(f, "{}", name), + } + } +} + impl<'tcx> RegionInferenceContext<'tcx> { /// Maps from an internal MIR region vid to something that we can /// report to the user. In some cases, the region vids will map @@ -57,7 +85,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder, - ) -> InternedString { + ) -> RegionName { debug!("give_region_a_name(fr={:?}, counter={})", fr, counter); assert!(self.universal_regions.is_universal_region(fr)); @@ -95,27 +123,31 @@ fn give_name_from_error_region( fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let error_region = self.to_error_region(fr)?; debug!("give_region_a_name: error_region = {:?}", error_region); match error_region { ty::ReEarlyBound(ebr) => { if ebr.has_name() { - self.highlight_named_span(tcx, error_region, &ebr.name, diag); - Some(ebr.name) + let name = RegionName::Named(ebr.name); + self.highlight_named_span(tcx, error_region, &name, diag); + Some(name) } else { None } } - ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()), + ty::ReStatic => Some(RegionName::Named( + keywords::StaticLifetime.name().as_interned_str() + )), ty::ReFree(free_region) => match free_region.bound_region { ty::BoundRegion::BrNamed(_, name) => { + let name = RegionName::Named(name); self.highlight_named_span(tcx, error_region, &name, diag); Some(name) - } + }, ty::BoundRegion::BrEnv => { let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); @@ -132,7 +164,10 @@ fn give_name_from_error_region( let region_name = self.synthesize_region_name(counter); diag.span_label( args_span, - format!("lifetime `{}` represents this closure's body", region_name), + format!( + "lifetime `{}` represents this closure's body", + region_name + ), ); let closure_kind_ty = substs.closure_kind_ty(def_id, tcx); @@ -174,6 +209,26 @@ fn give_name_from_error_region( } } + /// Get the span of a named region. + pub(super) fn get_span_of_named_region( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + error_region: &RegionKind, + name: &RegionName, + ) -> Span { + let scope = error_region.free_region_binding_scope(tcx); + let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); + + let span = tcx.sess.source_map().def_span(tcx.hir.span(node)); + if let Some(param) = tcx.hir.get_generics(scope).and_then(|generics| { + generics.get_named(name.as_interned_string()) + }) { + param.span + } else { + span + } + } + /// Highlight a named span to provide context for error messages that /// mention that span, for example: /// @@ -192,23 +247,15 @@ fn highlight_named_span( &self, tcx: TyCtxt<'_, '_, 'tcx>, error_region: &RegionKind, - name: &InternedString, + name: &RegionName, diag: &mut DiagnosticBuilder<'_>, ) { - let cm = tcx.sess.source_map(); + let span = self.get_span_of_named_region(tcx, error_region, name); - let scope = error_region.free_region_binding_scope(tcx); - let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); - - let mut sp = cm.def_span(tcx.hir.span(node)); - if let Some(param) = tcx.hir - .get_generics(scope) - .and_then(|generics| generics.get_named(name)) - { - sp = param.span; - } - - diag.span_label(sp, format!("lifetime `{}` defined here", name)); + diag.span_label( + span, + format!("lifetime `{}` defined here", name), + ); } /// Find an argument that contains `fr` and label it with a fully @@ -227,7 +274,7 @@ fn give_name_if_anonymous_region_appears_in_arguments( fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?; @@ -259,7 +306,7 @@ fn give_name_if_we_can_match_hir_ty_from_argument( argument_index: usize, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id)?; let fn_decl = infcx.tcx.hir.fn_decl(mir_node_id)?; let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index]; @@ -306,7 +353,7 @@ fn give_name_if_we_cannot_match_hir_ty( argument_ty: Ty<'tcx>, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let type_name = with_highlight_region(needle_fr, *counter, || { infcx.extract_type_name(&argument_ty) }); @@ -361,7 +408,7 @@ fn give_name_if_we_can_match_hir_ty( argument_hir_ty: &hir::Ty, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut Vec::new(); search_stack.push((argument_ty, argument_hir_ty)); @@ -457,7 +504,7 @@ fn match_adt_and_segment<'hir>( counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>, - ) -> Option { + ) -> Option { // Did the user give explicit arguments? (e.g., `Foo<..>`) let args = last_segment.args.as_ref()?; let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?; @@ -467,7 +514,10 @@ fn match_adt_and_segment<'hir>( | hir::LifetimeName::Underscore => { let region_name = self.synthesize_region_name(counter); let ampersand_span = lifetime.span; - diag.span_label(ampersand_span, format!("let's call this `{}`", region_name)); + diag.span_label( + ampersand_span, + format!("let's call this `{}`", region_name) + ); return Some(region_name); } @@ -544,7 +594,7 @@ fn give_name_if_anonymous_region_appears_in_upvars( fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let upvar_index = self.get_upvar_index_for_region(tcx, fr)?; let (upvar_name, upvar_span) = self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index); @@ -573,7 +623,7 @@ fn give_name_if_anonymous_region_appears_in_output( fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, - ) -> Option { + ) -> Option { let tcx = infcx.tcx; let return_ty = self.universal_regions.unnormalized_output_ty; @@ -622,10 +672,10 @@ fn give_name_if_anonymous_region_appears_in_output( /// Create a synthetic region named `'1`, incrementing the /// counter. - fn synthesize_region_name(&self, counter: &mut usize) -> InternedString { + fn synthesize_region_name(&self, counter: &mut usize) -> RegionName { let c = *counter; *counter += 1; - Name::intern(&format!("'{:?}", c)).as_interned_str() + RegionName::Synthesized(Name::intern(&format!("'{:?}", c)).as_interned_str()) } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 214628600b3..d1713a520a7 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -26,8 +26,8 @@ }; use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc::util::common; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::graph::scc::Sccs; -use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::{DiagnosticBuilder, Diagnostic}; @@ -477,7 +477,7 @@ fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) { // SCC. For each SCC, we visit its successors and compute // their values, then we union all those values to get our // own. - let visited = &mut IdxSet::new_empty(self.constraint_sccs.num_sccs()); + let visited = &mut BitSet::new_empty(self.constraint_sccs.num_sccs()); for scc_index in self.constraint_sccs.all_sccs() { self.propagate_constraint_sccs_if_new(scc_index, visited); } @@ -487,9 +487,9 @@ fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) { fn propagate_constraint_sccs_if_new( &mut self, scc_a: ConstraintSccIndex, - visited: &mut IdxSet, + visited: &mut BitSet, ) { - if visited.add(&scc_a) { + if visited.insert(scc_a) { self.propagate_constraint_sccs_new(scc_a, visited); } } @@ -497,7 +497,7 @@ fn propagate_constraint_sccs_if_new( fn propagate_constraint_sccs_new( &mut self, scc_a: ConstraintSccIndex, - visited: &mut IdxSet, + visited: &mut BitSet, ) { let constraint_sccs = self.constraint_sccs.clone(); diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 3dafab2f5a9..8dc41a9b2d3 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -10,7 +10,7 @@ use rustc::mir::{BasicBlock, Location, Mir}; use rustc::ty::{self, RegionVid}; -use rustc_data_structures::bitvec::{BitArray, SparseBitMatrix}; +use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt::Debug; @@ -179,19 +179,19 @@ impl LivenessValues { crate fn add_element(&mut self, row: N, location: Location) -> bool { debug!("LivenessValues::add(r={:?}, location={:?})", row, location); let index = self.elements.point_from_location(location); - self.points.add(row, index) + self.points.insert(row, index) } /// Adds all the elements in the given bit array into the given /// region. Returns true if any of them are newly added. - crate fn add_elements(&mut self, row: N, locations: &BitArray) -> bool { + crate fn add_elements(&mut self, row: N, locations: &HybridBitSet) -> bool { debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); - self.points.merge_into(row, locations) + self.points.union_into_row(row, locations) } /// Adds all the control-flow points to the values for `r`. crate fn add_all_points(&mut self, row: N) { - self.points.add_all(row); + self.points.insert_all_into_row(row); } /// True if the region `r` contains the given element. @@ -270,15 +270,15 @@ impl RegionValues { /// Adds all the control-flow points to the values for `r`. crate fn add_all_points(&mut self, r: N) { - self.points.add_all(r); + self.points.insert_all_into_row(r); } /// Add all elements in `r_from` to `r_to` (because e.g. `r_to: /// r_from`). crate fn add_region(&mut self, r_to: N, r_from: N) -> bool { - self.points.merge(r_from, r_to) - | self.free_regions.merge(r_from, r_to) - | self.placeholders.merge(r_from, r_to) + self.points.union_rows(r_from, r_to) + | self.free_regions.union_rows(r_from, r_to) + | self.placeholders.union_rows(r_from, r_to) } /// True if the region `r` contains the given element. @@ -291,7 +291,7 @@ impl RegionValues { /// the region `to` in `self`. crate fn merge_liveness(&mut self, to: N, from: M, values: &LivenessValues) { if let Some(set) = values.points.row(from) { - self.points.merge_into(to, set); + self.points.union_into_row(to, set); } } @@ -300,7 +300,7 @@ impl RegionValues { crate fn contains_points(&self, sup_region: N, sub_region: N) -> bool { if let Some(sub_row) = self.points.row(sub_region) { if let Some(sup_row) = self.points.row(sup_region) { - sup_row.contains_all(sub_row) + sup_row.superset(sub_row) } else { // sup row is empty, so sub row must be empty sub_row.is_empty() @@ -378,7 +378,7 @@ impl RegionValues { impl ToElementIndex for Location { fn add_to_row(self, values: &mut RegionValues, row: N) -> bool { let index = values.elements.point_from_location(self); - values.points.add(row, index) + values.points.insert(row, index) } fn contained_in_row(self, values: &RegionValues, row: N) -> bool { @@ -389,7 +389,7 @@ fn contained_in_row(self, values: &RegionValues, row: N) -> bool { impl ToElementIndex for RegionVid { fn add_to_row(self, values: &mut RegionValues, row: N) -> bool { - values.free_regions.add(row, self) + values.free_regions.insert(row, self) } fn contained_in_row(self, values: &RegionValues, row: N) -> bool { @@ -400,7 +400,7 @@ fn contained_in_row(self, values: &RegionValues, row: N) -> bool { impl ToElementIndex for ty::UniverseIndex { fn add_to_row(self, values: &mut RegionValues, row: N) -> bool { let index = PlaceholderIndex::new(self.as_usize() - 1); - values.placeholders.add(row, index) + values.placeholders.insert(row, index) } fn contained_in_row(self, values: &RegionValues, row: N) -> bool { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 79589ce9733..47e6ce05cec 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -22,7 +22,7 @@ use rustc::traits::query::type_op::outlives::DropckOutlives; use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::HybridBitSet; use rustc_data_structures::fx::FxHashMap; use std::rc::Rc; use util::liveness::LiveVariableMap; @@ -121,16 +121,16 @@ struct LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx> cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>, /// Set of points that define the current local. - defs: BitArray, + defs: HybridBitSet, /// Points where the current variable is "use live" -- meaning /// that there is a future "full use" that may use its value. - use_live_at: BitArray, + use_live_at: HybridBitSet, /// Points where the current variable is "drop live" -- meaning /// that there is no future "full use" that may use its value, but /// there is a future drop. - drop_live_at: BitArray, + drop_live_at: HybridBitSet, /// Locations where drops may occur. drop_locations: Vec, @@ -144,9 +144,9 @@ fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { cx, - defs: BitArray::new(num_points), - use_live_at: BitArray::new(num_points), - drop_live_at: BitArray::new(num_points), + defs: HybridBitSet::new_empty(num_points), + use_live_at: HybridBitSet::new_empty(num_points), + drop_live_at: HybridBitSet::new_empty(num_points), drop_locations: vec![], stack: vec![], } @@ -448,7 +448,7 @@ fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool fn add_use_live_facts_for( &mut self, value: impl TypeFoldable<'tcx>, - live_at: &BitArray, + live_at: &HybridBitSet, ) { debug!("add_use_live_facts_for(value={:?})", value); @@ -465,7 +465,7 @@ fn add_drop_live_facts_for( dropped_local: Local, dropped_ty: Ty<'tcx>, drop_locations: &[Location], - live_at: &BitArray, + live_at: &HybridBitSet, ) { debug!( "add_drop_live_constraint(\ @@ -508,7 +508,7 @@ fn make_all_regions_live( elements: &RegionValueElements, typeck: &mut TypeChecker<'_, '_, 'tcx>, value: impl TypeFoldable<'tcx>, - live_at: &BitArray, + live_at: &HybridBitSet, ) { debug!("make_all_regions_live(value={:?})", value); debug!( diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index d46b0813ca7..8e40fd19941 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -51,7 +51,7 @@ pub fn push_end_region<'a, 'gcx:'a+'tcx>(&mut self, source_info: SourceInfo, region_scope: region::Scope) { if tcx.emit_end_regions() { - if let region::ScopeData::CallSite = region_scope.data() { + if let region::ScopeData::CallSite = region_scope.data { // The CallSite scope (aka the root scope) is sort of weird, in that it is // supposed to "separate" the "interior" and "exterior" of a closure. Being // that, it is not really a part of the region hierarchy, but for some diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index cef1fb77e5c..49c4ed874bb 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -21,7 +21,7 @@ use rustc::hir; use rustc::mir::*; use rustc::ty::{self, CanonicalTy, Ty}; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Name, NodeId}; use syntax_pos::Span; @@ -635,7 +635,7 @@ enum TestKind<'tcx> { // test the branches of enum Switch { adt_def: &'tcx ty::AdtDef, - variants: BitArray, + variants: BitSet, }, // test the branches of enum diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 373c8e039f8..caef3ef80db 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -18,8 +18,8 @@ use build::Builder; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::bitvec::BitArray; use rustc::ty::{self, Ty}; use rustc::ty::util::IntTypeExt; use rustc::mir::*; @@ -38,7 +38,7 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { span: match_pair.pattern.span, kind: TestKind::Switch { adt_def: adt_def.clone(), - variants: BitArray::new(adt_def.variants.len()), + variants: BitSet::new_empty(adt_def.variants.len()), }, } } @@ -152,7 +152,7 @@ pub fn add_cases_to_switch<'pat>(&mut self, pub fn add_variants_to_switch<'pat>(&mut self, test_place: &Place<'tcx>, candidate: &Candidate<'pat, 'tcx>, - variants: &mut BitArray) + variants: &mut BitSet) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 576c91a02b0..d2061d8eecf 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -550,8 +550,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, upvar_decls); let fn_def_id = tcx.hir.local_def_id(fn_id); - let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id); - let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id); + let call_site_scope = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + }; + let arg_scope = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Arguments + }; let mut block = START_BLOCK; let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 1406183955b..cc5b08f2a90 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -565,7 +565,7 @@ pub fn region_scope_of_return_scope(&self) -> region::Scope { // The outermost scope (`scopes[0]`) will be the `CallSiteScope`. // We want `scopes[1]`, which is the `ParameterScope`. assert!(self.scopes.len() >= 2); - assert!(match self.scopes[1].region_scope.data() { + assert!(match self.scopes[1].region_scope.data { region::ScopeData::Arguments => true, _ => false, }); diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index 39643af77a1..d815bfedc37 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -12,8 +12,7 @@ //! locations. use rustc::mir::{BasicBlock, Location}; -use rustc_data_structures::bitvec::BitIter; -use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet}; +use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet}; use dataflow::{BitDenotation, BlockSets, DataflowResults}; use dataflow::move_paths::{HasMoveData, MovePathIndex}; @@ -76,9 +75,9 @@ pub struct FlowAtLocation BD: BitDenotation, { base_results: DataflowResults, - curr_state: IdxSet, - stmt_gen: HybridIdxSet, - stmt_kill: HybridIdxSet, + curr_state: BitSet, + stmt_gen: HybridBitSet, + stmt_kill: HybridBitSet, } impl FlowAtLocation @@ -105,9 +104,9 @@ pub fn each_gen_bit(&self, f: F) pub fn new(results: DataflowResults) -> Self { let bits_per_block = results.sets().bits_per_block(); - let curr_state = IdxSet::new_empty(bits_per_block); - let stmt_gen = HybridIdxSet::new_empty(bits_per_block); - let stmt_kill = HybridIdxSet::new_empty(bits_per_block); + let curr_state = BitSet::new_empty(bits_per_block); + let stmt_gen = HybridBitSet::new_empty(bits_per_block); + let stmt_kill = HybridBitSet::new_empty(bits_per_block); FlowAtLocation { base_results: results, curr_state: curr_state, @@ -121,7 +120,7 @@ pub fn operator(&self) -> &BD { self.base_results.operator() } - pub fn contains(&self, x: &BD::Idx) -> bool { + pub fn contains(&self, x: BD::Idx) -> bool { self.curr_state.contains(x) } @@ -224,7 +223,7 @@ pub fn has_any_child_of(&self, mpi: T::Idx) -> Option { // siblings); // - ~99% of the time the loop isn't reached, and this code is hot, so // we don't want to allocate `todo` unnecessarily. - if self.contains(&mpi) { + if self.contains(mpi) { return Some(mpi); } let move_data = self.operator().move_data(); @@ -236,7 +235,7 @@ pub fn has_any_child_of(&self, mpi: T::Idx) -> Option { }; while let Some(mpi) = todo.pop() { - if self.contains(&mpi) { + if self.contains(mpi) { return Some(mpi); } let move_path = &move_data.move_paths[mpi]; diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 9487147ea9d..45baab844ab 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -12,7 +12,6 @@ use syntax::ast::NodeId; use rustc::mir::{BasicBlock, Mir}; -use rustc_data_structures::bitvec::bits_to_string; use dot; use dot::IntoCow; @@ -223,7 +222,7 @@ fn node_label_final_row(&self, // Entry let set = flow.sets.on_entry_set_for(i); - write!(w, "{:?}", dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?; + write!(w, "{:?}", dot::escape_html(&set.to_string(bits_per_block)))?; // Terminator write!(w, "")?; diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index c8c41c13b0f..8d186597b14 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -43,7 +43,7 @@ fn bits_per_block(&self) -> usize { self.mir.local_decls.len() } - fn start_block_effect(&self, _sets: &mut IdxSet) { + fn start_block_effect(&self, _sets: &mut BitSet) { // Nothing is borrowed on function entry } @@ -58,7 +58,7 @@ fn statement_effect(&self, // StorageDead invalidates all borrows and raw pointers to a local match stmt.kind { - StatementKind::StorageDead(l) => sets.kill(&l), + StatementKind::StorageDead(l) => sets.kill(l), _ => (), } } @@ -72,7 +72,7 @@ fn terminator_effect(&self, } fn propagate_call_return(&self, - _in_out: &mut IdxSet, + _in_out: &mut BitSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { @@ -80,10 +80,10 @@ fn propagate_call_return(&self, } } -impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> { +impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // "maybe" means we union effects of both preds + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.union(in_set) // "maybe" means we union effects of both preds } } @@ -118,7 +118,7 @@ fn visit_rvalue(&mut self, location: Location) { if let Rvalue::Ref(_, _, ref place) = *rvalue { if let Some(local) = find_local(place) { - self.sets.gen(&local); + self.sets.gen(local); } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 66f020faa87..010ffafc4bd 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -20,10 +20,9 @@ use rustc::ty::{RegionKind, RegionVid}; use rustc::ty::RegionKind::ReScope; -use rustc_data_structures::bitvec::{BitwiseOperator, Word}; +use rustc_data_structures::bit_set::{BitSet, BitSetOperator}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::indexed_set::IdxSet; -use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sync::Lrc; use dataflow::{BitDenotation, BlockSets, InitialFlow}; @@ -157,7 +156,10 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { ) -> Self { let scope_tree = tcx.region_scope_tree(def_id); let root_scope = body_id.map(|body_id| { - region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) + region::Scope { + id: tcx.hir.body(body_id).value.hir_id.local_id, + data: region::ScopeData::CallSite + } }); let mut borrows_out_of_scope_at_location = FxHashMap(); @@ -227,7 +229,7 @@ fn bits_per_block(&self) -> usize { self.borrow_set.borrows.len() * 2 } - fn start_block_effect(&self, _entry_set: &mut IdxSet) { + fn start_block_effect(&self, _entry_set: &mut BitSet) { // no borrows of code region_scopes have been taken prior to // function execution, so this method has no effect on // `_sets`. @@ -286,7 +288,7 @@ fn statement_effect(&self, sets: &mut BlockSets, location: Location debug!("Borrows::statement_effect_on_borrows \ location: {:?} stmt: {:?} has empty region, killing {:?}", location, stmt.kind, index); - sets.kill(&index); + sets.kill(*index); return } else { debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}", @@ -296,7 +298,7 @@ fn statement_effect(&self, sets: &mut BlockSets, location: Location assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| { panic!("could not find BorrowIndexs for region {:?}", region); }).contains(&index)); - sets.gen(&index); + sets.gen(*index); // Issue #46746: Two-phase borrows handles // stmts of form `Tmp = &mut Borrow` ... @@ -308,7 +310,7 @@ fn statement_effect(&self, sets: &mut BlockSets, location: Location // e.g. `box (&mut _)`. Current // conservative solution: force // immediate activation here. - sets.gen(&index); + sets.gen(*index); } } } @@ -378,7 +380,7 @@ fn terminator_effect(&self, sets: &mut BlockSets, location: Locatio if *scope != root_scope && self.scope_tree.is_subscope_of(*scope, root_scope) { - sets.kill(&borrow_index); + sets.kill(borrow_index); } } } @@ -399,7 +401,7 @@ fn terminator_effect(&self, sets: &mut BlockSets, location: Locatio } fn propagate_call_return(&self, - _in_out: &mut IdxSet, + _in_out: &mut BitSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { @@ -411,10 +413,10 @@ fn propagate_call_return(&self, } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitSetOperator for Borrows<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // union effects of preds when computing reservations + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.union(in_set) // "maybe" means we union effects of both preds } } diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index c8f70479852..984d1f686d9 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,8 +14,7 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitvec::{BitwiseOperator, Word}; -use rustc_data_structures::indexed_set::{IdxSet}; +use rustc_data_structures::bit_set::{BitSet, BitSetOperator}; use rustc_data_structures::indexed_vec::Idx; use super::MoveDataParamEnv; @@ -266,8 +265,8 @@ fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { match state { - DropFlagState::Absent => sets.kill(&path), - DropFlagState::Present => sets.gen(&path), + DropFlagState::Absent => sets.kill(path), + DropFlagState::Present => sets.gen(path), } } } @@ -277,8 +276,8 @@ fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { match state { - DropFlagState::Absent => sets.gen(&path), - DropFlagState::Present => sets.kill(&path), + DropFlagState::Absent => sets.gen(path), + DropFlagState::Present => sets.kill(path), } } } @@ -288,8 +287,8 @@ fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { match state { - DropFlagState::Absent => sets.kill(&path), - DropFlagState::Present => sets.gen(&path), + DropFlagState::Absent => sets.kill(path), + DropFlagState::Present => sets.gen(path), } } } @@ -301,12 +300,12 @@ fn bits_per_block(&self) -> usize { self.move_data().move_paths.len() } - fn start_block_effect(&self, entry_set: &mut IdxSet) { + fn start_block_effect(&self, entry_set: &mut BitSet) { drop_flag_effects_for_function_entry( self.tcx, self.mir, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); - entry_set.add(&path); + entry_set.insert(path); }); } @@ -333,7 +332,7 @@ fn terminator_effect(&self, } fn propagate_call_return(&self, - in_out: &mut IdxSet, + in_out: &mut BitSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_place: &mir::Place) { @@ -341,7 +340,7 @@ fn propagate_call_return(&self, // the bits for that dest_place to 1 (initialized). on_lookup_result_bits(self.tcx, self.mir, self.move_data(), self.move_data().rev_lookup.find(dest_place), - |mpi| { in_out.add(&mpi); }); + |mpi| { in_out.insert(mpi); }); } } @@ -353,7 +352,7 @@ fn bits_per_block(&self) -> usize { } // sets on_entry bits for Arg places - fn start_block_effect(&self, entry_set: &mut IdxSet) { + fn start_block_effect(&self, entry_set: &mut BitSet) { // set all bits to 1 (uninit) before gathering counterevidence entry_set.set_up_to(self.bits_per_block()); @@ -361,7 +360,7 @@ fn start_block_effect(&self, entry_set: &mut IdxSet) { self.tcx, self.mir, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); - entry_set.remove(&path); + entry_set.remove(path); }); } @@ -388,7 +387,7 @@ fn terminator_effect(&self, } fn propagate_call_return(&self, - in_out: &mut IdxSet, + in_out: &mut BitSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_place: &mir::Place) { @@ -396,7 +395,7 @@ fn propagate_call_return(&self, // the bits for that dest_place to 0 (initialized). on_lookup_result_bits(self.tcx, self.mir, self.move_data(), self.move_data().rev_lookup.find(dest_place), - |mpi| { in_out.remove(&mpi); }); + |mpi| { in_out.remove(mpi); }); } } @@ -408,14 +407,14 @@ fn bits_per_block(&self) -> usize { } // sets on_entry bits for Arg places - fn start_block_effect(&self, entry_set: &mut IdxSet) { + fn start_block_effect(&self, entry_set: &mut BitSet) { entry_set.clear(); drop_flag_effects_for_function_entry( self.tcx, self.mir, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); - entry_set.add(&path); + entry_set.insert(path); }); } @@ -442,7 +441,7 @@ fn terminator_effect(&self, } fn propagate_call_return(&self, - in_out: &mut IdxSet, + in_out: &mut BitSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_place: &mir::Place) { @@ -450,7 +449,7 @@ fn propagate_call_return(&self, // the bits for that dest_place to 1 (initialized). on_lookup_result_bits(self.tcx, self.mir, self.move_data(), self.move_data().rev_lookup.find(dest_place), - |mpi| { in_out.add(&mpi); }); + |mpi| { in_out.insert(mpi); }); } } @@ -461,9 +460,9 @@ fn bits_per_block(&self) -> usize { self.move_data().inits.len() } - fn start_block_effect(&self, entry_set: &mut IdxSet) { + fn start_block_effect(&self, entry_set: &mut BitSet) { for arg_init in 0..self.mir.arg_count { - entry_set.add(&InitIndex::new(arg_init)); + entry_set.insert(InitIndex::new(arg_init)); } } @@ -531,7 +530,7 @@ fn terminator_effect(&self, } fn propagate_call_return(&self, - in_out: &mut IdxSet, + in_out: &mut BitSet, call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { @@ -545,36 +544,36 @@ fn propagate_call_return(&self, }; for init_index in &init_loc_map[call_loc] { assert!(init_index.index() < bits_per_block); - in_out.add(init_index); + in_out.insert(*init_index); } } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitSetOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // "maybe" means we union effects of both preds + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.union(in_set) // "maybe" means we union effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitSetOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // "maybe" means we union effects of both preds + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.union(in_set) // "maybe" means we union effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitSetOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 & pred2 // "definitely" means we intersect effects of both preds + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.intersect(in_set) // "definitely" means we intersect effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitSetOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // inits from both preds are in scope + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.union(in_set) // inits from both preds are in scope } } diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 29548051a4d..ab03ace23d7 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -36,7 +36,7 @@ fn bits_per_block(&self) -> usize { self.mir.local_decls.len() } - fn start_block_effect(&self, _sets: &mut IdxSet) { + fn start_block_effect(&self, _sets: &mut BitSet) { // Nothing is live on function entry } @@ -46,8 +46,8 @@ fn statement_effect(&self, let stmt = &self.mir[loc.block].statements[loc.statement_index]; match stmt.kind { - StatementKind::StorageLive(l) => sets.gen(&l), - StatementKind::StorageDead(l) => sets.kill(&l), + StatementKind::StorageLive(l) => sets.gen(l), + StatementKind::StorageDead(l) => sets.kill(l), _ => (), } } @@ -59,7 +59,7 @@ fn terminator_effect(&self, } fn propagate_call_return(&self, - _in_out: &mut IdxSet, + _in_out: &mut BitSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { @@ -67,10 +67,10 @@ fn propagate_call_return(&self, } } -impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> { +impl<'a, 'tcx> BitSetOperator for MaybeStorageLive<'a, 'tcx> { #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // "maybe" means we union effects of both preds + fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { + inout_set.union(in_set) // "maybe" means we union effects of both preds } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 49d75d31fc7..1e362e6f0dc 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -10,8 +10,7 @@ use syntax::ast::{self, MetaItem}; -use rustc_data_structures::bitvec::{bitwise, BitwiseOperator}; -use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet}; +use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::work_queue::WorkQueue; @@ -125,7 +124,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, node_id: ast::NodeId, attributes: &[ast::Attribute], - dead_unwinds: &IdxSet, + dead_unwinds: &BitSet, bd: BD, p: P) -> DataflowResults @@ -182,7 +181,7 @@ struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation { fn propagate(&mut self) { - let mut temp = IdxSet::new_empty(self.flow_state.sets.bits_per_block); + let mut temp = BitSet::new_empty(self.flow_state.sets.bits_per_block); let mut propcx = PropagationContext { builder: self, }; @@ -231,7 +230,7 @@ fn build_sets(&mut self) { impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation { - fn walk_cfg(&mut self, in_out: &mut IdxSet) { + fn walk_cfg(&mut self, in_out: &mut BitSet) { let mut dirty_queue: WorkQueue = WorkQueue::with_all(self.builder.mir.basic_blocks().len()); let mir = self.builder.mir; @@ -352,7 +351,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location, analysis: &T, result: &DataflowResults, mir: &Mir<'tcx>) - -> IdxSet { + -> BitSet { let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned(); let mut kill_set = on_entry.to_hybrid(); let mut gen_set = kill_set.clone(); @@ -385,7 +384,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location, pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation { flow_state: DataflowState, - dead_unwinds: &'a IdxSet, + dead_unwinds: &'a BitSet, mir: &'a Mir<'tcx>, } @@ -426,7 +425,7 @@ pub struct DataflowState impl DataflowState { pub(crate) fn interpret_set<'c, P>(&self, o: &'c O, - set: &IdxSet, + set: &BitSet, render_idx: &P) -> Vec where P: Fn(&O, O::Idx) -> DebugFormatted @@ -436,7 +435,7 @@ pub(crate) fn interpret_set<'c, P>(&self, pub(crate) fn interpret_hybrid_set<'c, P>(&self, o: &'c O, - set: &HybridIdxSet, + set: &HybridBitSet, render_idx: &P) -> Vec where P: Fn(&O, O::Idx) -> DebugFormatted @@ -451,21 +450,21 @@ pub struct AllSets { bits_per_block: usize, /// For each block, bits valid on entry to the block. - on_entry_sets: Vec>, + on_entry_sets: Vec>, /// For each block, bits generated by executing the statements + /// terminator in the block -- with one caveat. In particular, for /// *call terminators*, the effect of storing the destination is /// not included, since that only takes effect on the **success** /// edge (and not the unwind edge). - gen_sets: Vec>, + gen_sets: Vec>, /// For each block, bits killed by executing the statements + /// terminator in the block -- with one caveat. In particular, for /// *call terminators*, the effect of storing the destination is /// not included, since that only takes effect on the **success** /// edge (and not the unwind edge). - kill_sets: Vec>, + kill_sets: Vec>, } /// Triple of sets associated with a given block. @@ -485,20 +484,20 @@ pub struct AllSets { #[derive(Debug)] pub struct BlockSets<'a, E: Idx> { /// Dataflow state immediately before control flow enters the given block. - pub(crate) on_entry: &'a mut IdxSet, + pub(crate) on_entry: &'a mut BitSet, /// Bits that are set to 1 by the time we exit the given block. Hybrid /// because it usually contains only 0 or 1 elements. - pub(crate) gen_set: &'a mut HybridIdxSet, + pub(crate) gen_set: &'a mut HybridBitSet, /// Bits that are set to 0 by the time we exit the given block. Hybrid /// because it usually contains only 0 or 1 elements. - pub(crate) kill_set: &'a mut HybridIdxSet, + pub(crate) kill_set: &'a mut HybridBitSet, } impl<'a, E:Idx> BlockSets<'a, E> { - fn gen(&mut self, e: &E) { - self.gen_set.add(e); + fn gen(&mut self, e: E) { + self.gen_set.insert(e); self.kill_set.remove(e); } fn gen_all(&mut self, i: I) @@ -506,13 +505,13 @@ fn gen_all(&mut self, i: I) I::Item: Borrow { for j in i { - self.gen(j.borrow()); + self.gen(*j.borrow()); } } - fn kill(&mut self, e: &E) { + fn kill(&mut self, e: E) { self.gen_set.remove(e); - self.kill_set.add(e); + self.kill_set.insert(e); } fn kill_all(&mut self, i: I) @@ -520,7 +519,7 @@ fn kill_all(&mut self, i: I) I::Item: Borrow { for j in i { - self.kill(j.borrow()); + self.kill(*j.borrow()); } } @@ -540,13 +539,13 @@ pub fn for_block(&mut self, block_idx: usize) -> BlockSets { } } - pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet { + pub fn on_entry_set_for(&self, block_idx: usize) -> &BitSet { &self.on_entry_sets[block_idx] } - pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSet { + pub fn gen_set_for(&self, block_idx: usize) -> &HybridBitSet { &self.gen_sets[block_idx] } - pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSet { + pub fn kill_set_for(&self, block_idx: usize) -> &HybridBitSet { &self.kill_sets[block_idx] } } @@ -562,7 +561,7 @@ pub trait InitialFlow { fn bottom_value() -> bool; } -pub trait BitDenotation: BitwiseOperator { +pub trait BitDenotation: BitSetOperator { /// Specifies what index type is used to access the bitvector. type Idx: Idx; @@ -609,7 +608,7 @@ fn accumulates_intrablock_state() -> bool { false } /// these won't be accounted for correctly. /// /// (For example, establishing the call arguments.) - fn start_block_effect(&self, entry_set: &mut IdxSet); + fn start_block_effect(&self, entry_set: &mut BitSet); /// Similar to `statement_effect`, except it applies /// *just before* the statement rather than *just after* it. @@ -689,7 +688,7 @@ fn terminator_effect(&self, /// kill-sets associated with each edge coming out of the basic /// block. fn propagate_call_return(&self, - in_out: &mut IdxSet, + in_out: &mut BitSet, call_bb: mir::BasicBlock, dest_bb: mir::BasicBlock, dest_place: &mir::Place); @@ -698,17 +697,17 @@ fn propagate_call_return(&self, impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation { pub fn new(mir: &'a Mir<'tcx>, - dead_unwinds: &'a IdxSet, + dead_unwinds: &'a BitSet, denotation: D) -> Self where D: InitialFlow { let bits_per_block = denotation.bits_per_block(); let num_blocks = mir.basic_blocks().len(); let on_entry_sets = if D::bottom_value() { - vec![IdxSet::new_filled(bits_per_block); num_blocks] + vec![BitSet::new_filled(bits_per_block); num_blocks] } else { - vec![IdxSet::new_empty(bits_per_block); num_blocks] + vec![BitSet::new_empty(bits_per_block); num_blocks] }; - let gen_sets = vec![HybridIdxSet::new_empty(bits_per_block); num_blocks]; + let gen_sets = vec![HybridBitSet::new_empty(bits_per_block); num_blocks]; let kill_sets = gen_sets.clone(); DataflowAnalysis { @@ -727,7 +726,7 @@ pub fn new(mir: &'a Mir<'tcx>, } pub fn new_from_sets(mir: &'a Mir<'tcx>, - dead_unwinds: &'a IdxSet, + dead_unwinds: &'a BitSet, sets: AllSets, denotation: D) -> Self { DataflowAnalysis { @@ -758,7 +757,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation /// unwind target). fn propagate_bits_into_graph_successors_of( &mut self, - in_out: &mut IdxSet, + in_out: &mut BitSet, (bb, bb_data): (mir::BasicBlock, &mir::BasicBlockData), dirty_list: &mut WorkQueue) { @@ -787,7 +786,7 @@ fn propagate_bits_into_graph_successors_of( target, value: _, location: _, unwind: Some(unwind) } => { self.propagate_bits_into_entry_set_for(in_out, target, dirty_list); - if !self.dead_unwinds.contains(&bb) { + if !self.dead_unwinds.contains(bb) { self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list); } } @@ -798,7 +797,7 @@ fn propagate_bits_into_graph_successors_of( } mir::TerminatorKind::Call { cleanup, ref destination, func: _, args: _ } => { if let Some(unwind) = cleanup { - if !self.dead_unwinds.contains(&bb) { + if !self.dead_unwinds.contains(bb) { self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list); } } @@ -819,7 +818,7 @@ fn propagate_bits_into_graph_successors_of( mir::TerminatorKind::FalseUnwind { real_target, unwind } => { self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list); if let Some(unwind) = unwind { - if !self.dead_unwinds.contains(&bb) { + if !self.dead_unwinds.contains(bb) { self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list); } } @@ -828,13 +827,11 @@ fn propagate_bits_into_graph_successors_of( } fn propagate_bits_into_entry_set_for(&mut self, - in_out: &IdxSet, + in_out: &BitSet, bb: mir::BasicBlock, dirty_queue: &mut WorkQueue) { - let entry_set = self.flow_state.sets.for_block(bb.index()).on_entry; - let set_changed = bitwise(entry_set.words_mut(), - in_out.words(), - &self.flow_state.operator); + let entry_set = &mut self.flow_state.sets.for_block(bb.index()).on_entry; + let set_changed = self.flow_state.operator.join(entry_set, &in_out); if set_changed { dirty_queue.insert(bb); } diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 7d7da6c96e8..58a2b936103 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -97,6 +97,20 @@ pub struct MovePath<'tcx> { pub place: Place<'tcx>, } +impl<'tcx> MovePath<'tcx> { + pub fn parents(&self, move_paths: &IndexVec) -> Vec { + let mut parents = Vec::new(); + + let mut curr_parent = self.parent; + while let Some(parent_mpi) = curr_parent { + parents.push(parent_mpi); + curr_parent = move_paths[parent_mpi].parent; + } + + parents + } +} + impl<'tcx> fmt::Debug for MovePath<'tcx> { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { write!(w, "MovePath {{")?; diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index b0a60fedfbb..2ab0a57a855 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -27,7 +27,10 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> { cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id); Block { targeted_by_break: self.targeted_by_break, - region_scope: region::Scope::Node(self.hir_id.local_id), + region_scope: region::Scope { + id: self.hir_id.local_id, + data: region::ScopeData::Node + }, opt_destruction_scope, span: self.span, stmts, @@ -59,7 +62,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::StmtKind::Semi(ref expr, _) => { result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Expr { - scope: region::Scope::Node(hir_id.local_id), + scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node + }, expr: expr.to_ref(), }, opt_destruction_scope: opt_dxn_ext, @@ -71,10 +77,11 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // ignore for purposes of the MIR } hir::DeclKind::Local(ref local) => { - let remainder_scope = region::Scope::Remainder( - block_id, - region::FirstStatementIndex::new(index), - ); + let remainder_scope = region::Scope { + id: block_id, + data: region::ScopeData::Remainder( + region::FirstStatementIndex::new(index)), + }; let mut pattern = cx.pattern_from_hir(&local.pat); @@ -94,7 +101,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { remainder_scope: remainder_scope, - init_scope: region::Scope::Node(hir_id.local_id), + init_scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node + }, pattern, initializer: local.init.to_ref(), lint_level: cx.lint_level_of(local.id), diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 510e7eb9c63..3183f0f47ea 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -27,7 +27,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { let temp_lifetime = cx.region_scope_tree.temporary_scope(self.hir_id.local_id); - let expr_scope = region::Scope::Node(self.hir_id.local_id); + let expr_scope = region::Scope { + id: self.hir_id.local_id, + data: region::ScopeData::Node + }; debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); @@ -148,7 +151,10 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Convert this to a suitable `&foo` and // then an unsafe coercion. Limit the region to be just this // expression. - let region = ty::ReScope(region::Scope::Node(hir_expr.hir_id.local_id)); + let region = ty::ReScope(region::Scope { + id: hir_expr.hir_id.local_id, + data: region::ScopeData::Node + }); let region = cx.tcx.mk_region(region); expr = Expr { temp_lifetime, @@ -581,7 +587,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Break(dest, ref value) => { match dest.target_id { Ok(target_id) => ExprKind::Break { - label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(target_id).local_id), + label: region::Scope { + id: cx.tcx.hir.node_to_hir_id(target_id).local_id, + data: region::ScopeData::Node + }, value: value.to_ref(), }, Err(err) => bug!("invalid loop id for break: {}", err) @@ -590,7 +599,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Continue(dest) => { match dest.target_id { Ok(loop_id) => ExprKind::Continue { - label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(loop_id).local_id), + label: region::Scope { + id: cx.tcx.hir.node_to_hir_id(loop_id).local_id, + data: region::ScopeData::Node + }, }, Err(err) => bug!("invalid loop id for continue: {}", err) } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index bf878145e1f..23667d1b331 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -537,11 +537,15 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, "cannot bind by-move with sub-bindings") .span_label(p.span, "binds an already bound by-move value by moving it") .emit(); - } else if has_guard { - struct_span_err!(cx.tcx.sess, p.span, E0008, - "cannot bind by-move into a pattern guard") - .span_label(p.span, "moves value into pattern guard") - .emit(); + } else if has_guard && !cx.tcx.allow_bind_by_move_patterns_with_guards() { + let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008, + "cannot bind by-move into a pattern guard"); + err.span_label(p.span, "moves value into pattern guard"); + if cx.tcx.sess.opts.unstable_features.is_nightly_build() && cx.tcx.use_mir_borrowck() { + err.help("add #![feature(bind_by_move_pattern_guards)] to the \ + crate attributes to enable"); + } + err.emit(); } else if let Some(by_ref_span) = by_ref_span { struct_span_err!( cx.tcx.sess, @@ -613,10 +617,16 @@ fn borrow(&mut self, _: LoanCause) { match kind { ty::MutBorrow => { - struct_span_err!(self.cx.tcx.sess, span, E0301, - "cannot mutably borrow in a pattern guard") - .span_label(span, "borrowed mutably in pattern guard") - .emit(); + let mut err = struct_span_err!(self.cx.tcx.sess, span, E0301, + "cannot mutably borrow in a pattern guard"); + err.span_label(span, "borrowed mutably in pattern guard"); + if self.cx.tcx.sess.opts.unstable_features.is_nightly_build() && + self.cx.tcx.use_mir_borrowck() + { + err.help("add #![feature(bind_by_move_pattern_guards)] to the \ + crate attributes to enable"); + } + err.emit(); } ty::ImmBorrow | ty::UniqueImmBorrow => {} } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 3a8723ec2fd..fcb310f7045 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -51,6 +51,11 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { /// a static creates a copy here, in the machine. alloc_map: FxHashMap, Allocation)>, + /// To be able to compare pointers with NULL, and to check alignment for accesses + /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations + /// that do not exist any more. + dead_alloc_map: FxHashMap, + pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>, } @@ -74,6 +79,7 @@ pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self { Memory { data, alloc_map: FxHashMap::default(), + dead_alloc_map: FxHashMap::default(), tcx, } } @@ -150,6 +156,8 @@ pub fn deallocate( size_and_align: Option<(Size, Align)>, kind: MemoryKind, ) -> EvalResult<'tcx> { + debug!("deallocating: {}", ptr.alloc_id); + if ptr.offset.bytes() != 0 { return err!(DeallocateNonBasePtr); } @@ -189,23 +197,41 @@ pub fn deallocate( } } - debug!("deallocated : {}", ptr.alloc_id); + // Don't forget to remember size and align of this now-dead allocation + let old = self.dead_alloc_map.insert( + ptr.alloc_id, + (Size::from_bytes(alloc.bytes.len() as u64), alloc.align) + ); + if old.is_some() { + bug!("Nothing can be deallocated twice"); + } Ok(()) } - /// Check that the pointer is aligned AND non-NULL. This supports scalars - /// for the benefit of other parts of miri that need to check alignment even for ZST. + /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways: + /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated. pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> { // Check non-NULL/Undef, extract offset let (offset, alloc_align) = match ptr { Scalar::Ptr(ptr) => { - let alloc = self.get(ptr.alloc_id)?; - (ptr.offset.bytes(), alloc.align) + let (size, align) = self.get_size_and_align(ptr.alloc_id)?; + // check this is not NULL -- which we can ensure only if this is in-bounds + // of some (potentially dead) allocation. + if ptr.offset > size { + return err!(PointerOutOfBounds { + ptr, + access: true, + allocation_size: size, + }); + }; + // keep data for alignment check + (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { assert_eq!(size as u64, self.pointer_size().bytes()); assert!(bits < (1u128 << self.pointer_size().bits())); + // check this is not NULL if bits == 0 { return err!(InvalidNullPointerUsage); } @@ -306,6 +332,21 @@ pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> { } } + pub fn get_size_and_align(&self, id: AllocId) -> EvalResult<'tcx, (Size, Align)> { + Ok(match self.get(id) { + Ok(alloc) => (Size::from_bytes(alloc.bytes.len() as u64), alloc.align), + Err(err) => match err.kind { + EvalErrorKind::DanglingPointerDeref => + // This should be in the dead allocation map + *self.dead_alloc_map.get(&id).expect( + "allocation missing in dead_alloc_map" + ), + // E.g. a function ptr allocation + _ => return Err(err) + } + }) + } + pub fn get_mut( &mut self, id: AllocId, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 8bb93d09a2a..c7f84f76839 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -219,7 +219,7 @@ pub(super) fn try_read_value_from_mplace( } let (ptr, ptr_align) = mplace.to_scalar_ptr_align(); - if mplace.layout.size.bytes() == 0 { + if mplace.layout.is_zst() { // Not all ZSTs have a layout we would handle below, so just short-circuit them // all here. self.memory.check_align(ptr, ptr_align)?; @@ -376,14 +376,14 @@ pub fn operand_downcast( }) } - // Take an operand, representing a pointer, and dereference it -- that + // Take an operand, representing a pointer, and dereference it to a place -- that // will always be a MemPlace. pub(super) fn deref_operand( &self, src: OpTy<'tcx>, ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { let val = self.read_value(src)?; - trace!("deref to {} on {:?}", val.layout.ty, val); + trace!("deref to {} on {:?}", val.layout.ty, *val); Ok(self.ref_to_mplace(val)?) } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 64e0aeaaab7..0f03aa097c9 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -316,7 +316,10 @@ pub fn mplace_field( }; let ptr = base.ptr.ptr_offset(offset, self)?; - let align = base.align.min(field_layout.align); // only use static information + let align = base.align + // We do not look at `base.layout.align` nor `field_layout.align`, unlike + // codegen -- mostly to see if we can get away with that + .restrict_for_offset(offset); // must be last thing that happens Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout }) } @@ -612,7 +615,7 @@ fn write_value_to_mplace( // wrong type. // Nothing to do for ZSTs, other than checking alignment - if dest.layout.size.bytes() == 0 { + if dest.layout.is_zst() { self.memory.check_align(ptr, ptr_align)?; return Ok(()); } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 52bbffa7519..d50ef2242fa 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -210,7 +210,7 @@ use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode}; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter}; #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] @@ -231,7 +231,7 @@ pub struct InliningMap<'tcx> { // Contains one bit per mono item in the `targets` field. That bit // is true if that mono item needs to be inlined into every CGU. - inlines: BitVector, + inlines: GrowableBitSet, } impl<'tcx> InliningMap<'tcx> { @@ -240,7 +240,7 @@ fn new() -> InliningMap<'tcx> { InliningMap { index: FxHashMap(), targets: Vec::new(), - inlines: BitVector::with_capacity(1024), + inlines: GrowableBitSet::with_capacity(1024), } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index bf538112e41..92b6af8b51f 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -18,15 +18,14 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::bit_set::BitSet; +use std::fmt; +use syntax::ast; +use syntax_pos::Span; use transform::{MirPass, MirSource}; use util::patch::MirPatch; use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; -use syntax::ast; -use syntax_pos::Span; - -use std::fmt; pub struct ElaborateDrops; @@ -92,12 +91,12 @@ fn find_dead_unwinds<'a, 'tcx>( mir: &Mir<'tcx>, id: ast::NodeId, env: &MoveDataParamEnv<'tcx, 'tcx>) - -> IdxSet + -> BitSet { debug!("find_dead_unwinds({:?})", mir.span); // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. - let mut dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); + let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &env), @@ -111,7 +110,7 @@ fn find_dead_unwinds<'a, 'tcx>( let mut init_data = InitializationData { live: flow_inits.sets().on_entry_set_for(bb.index()).to_owned(), - dead: IdxSet::new_empty(env.move_data.move_paths.len()), + dead: BitSet::new_empty(env.move_data.move_paths.len()), }; debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}", bb, bb_data, init_data.live); @@ -138,7 +137,7 @@ fn find_dead_unwinds<'a, 'tcx>( debug!("find_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live); if !maybe_live { - dead_unwinds.add(&bb); + dead_unwinds.insert(bb); } } @@ -146,8 +145,8 @@ fn find_dead_unwinds<'a, 'tcx>( } struct InitializationData { - live: IdxSet, - dead: IdxSet + live: BitSet, + dead: BitSet } impl InitializationData { @@ -162,19 +161,19 @@ fn apply_location<'a,'tcx>(&mut self, loc, path, df); match df { DropFlagState::Present => { - self.live.add(&path); - self.dead.remove(&path); + self.live.insert(path); + self.dead.remove(path); } DropFlagState::Absent => { - self.dead.add(&path); - self.live.remove(&path); + self.dead.insert(path); + self.live.remove(path); } } }); } fn state(&self, path: MovePathIndex) -> (bool, bool) { - (self.live.contains(&path), self.dead.contains(&path)) + (self.live.contains(path), self.dead.contains(path)) } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 01edfd2bfc9..96111519550 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -69,7 +69,7 @@ use util::liveness::{self, IdentityMap}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::bit_set::BitSet; use std::borrow::Cow; use std::iter::once; use std::mem; @@ -331,7 +331,7 @@ fn visit_statement(&mut self, _location: Location) { match statement.kind { StatementKind::StorageLive(l) | - StatementKind::StorageDead(l) => { self.0.remove(&l); } + StatementKind::StorageDead(l) => { self.0.remove(l); } _ => (), } } @@ -341,7 +341,7 @@ fn visit_statement(&mut self, fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { - Place::Local(l) => { locals.0.add(&l); }, + Place::Local(l) => { locals.0.insert(l); }, Place::Promoted(_) | Place::Static(..) => (), Place::Projection(ref proj) => { @@ -376,7 +376,7 @@ fn locals_live_across_suspend_points( liveness::LiveVarSet, FxHashMap>, ) { - let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); // Calculate when MIR locals have live storage. This gives us an upper bound of their @@ -388,7 +388,7 @@ fn locals_live_across_suspend_points( // Find the MIR locals which do not use StorageLive/StorageDead statements. // The storage of these locals are always live. - let mut ignored = StorageIgnored(IdxSet::new_filled(mir.local_decls.len())); + let mut ignored = StorageIgnored(BitSet::new_filled(mir.local_decls.len())); ignored.visit_mir(mir); // Calculate the MIR locals which have been previously @@ -472,7 +472,7 @@ fn locals_live_across_suspend_points( } // The generator argument is ignored - set.remove(&self_arg()); + set.remove(self_arg()); (set, storage_liveness_map) } @@ -502,7 +502,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for (local, decl) in mir.local_decls.iter_enumerated() { // Ignore locals which are internal or not live - if !live_locals.contains(&local) || decl.internal { + if !live_locals.contains(local) || decl.internal { continue; } @@ -823,7 +823,7 @@ fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>, // Create StorageLive instructions for locals with live storage for i in 0..(mir.local_decls.len()) { let l = Local::new(i); - if point.storage_liveness.contains(&l) && !transform.remap.contains_key(&l) { + if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) { statements.push(Statement { source_info, kind: StatementKind::StorageLive(l), diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 31e437ce228..8689fde3ee6 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -14,7 +14,7 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::DefId; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; @@ -271,7 +271,7 @@ fn should_inline(&self, // Traverse the MIR manually so we can account for the effects of // inlining on the CFG. let mut work_list = vec![START_BLOCK]; - let mut visited = BitArray::new(callee_mir.basic_blocks().len()); + let mut visited = BitSet::new_empty(callee_mir.basic_blocks().len()); while let Some(bb) = work_list.pop() { if !visited.insert(bb.index()) { continue; } let blk = &callee_mir.basic_blocks()[bb]; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a2175dce33a..bc9cc7274d5 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -14,8 +14,7 @@ //! The Qualif flags below can be used to also provide better //! diagnostics as to why a constant rvalue wasn't promoted. -use rustc_data_structures::bitvec::BitArray; -use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashSet; use rustc::hir; @@ -116,7 +115,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { param_env: ty::ParamEnv<'tcx>, local_qualif: IndexVec>, qualif: Qualif, - const_fn_arg_vars: BitArray, + const_fn_arg_vars: BitSet, temp_promotion_state: IndexVec, promotion_candidates: Vec } @@ -151,7 +150,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env, local_qualif, qualif: Qualif::empty(), - const_fn_arg_vars: BitArray::new(mir.local_decls.len()), + const_fn_arg_vars: BitSet::new_empty(mir.local_decls.len()), temp_promotion_state: temps, promotion_candidates: vec![] } @@ -280,12 +279,12 @@ fn assign(&mut self, dest: &Place<'tcx>, location: Location) { } /// Qualify a whole const, static initializer or const fn. - fn qualify_const(&mut self) -> (Qualif, Lrc>) { + fn qualify_const(&mut self) -> (Qualif, Lrc>) { debug!("qualifying {} {:?}", self.mode, self.def_id); let mir = self.mir; - let mut seen_blocks = BitArray::new(mir.basic_blocks().len()); + let mut seen_blocks = BitSet::new_empty(mir.basic_blocks().len()); let mut bb = START_BLOCK; loop { seen_blocks.insert(bb.index()); @@ -383,14 +382,14 @@ fn qualify_const(&mut self) -> (Qualif, Lrc>) { // Collect all the temps we need to promote. - let mut promoted_temps = IdxSet::new_empty(self.temp_promotion_state.len()); + let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len()); for candidate in &self.promotion_candidates { match *candidate { Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => { match self.mir[bb].statements[stmt_idx].kind { StatementKind::Assign(_, Rvalue::Ref(_, _, Place::Local(index))) => { - promoted_temps.add(&index); + promoted_temps.insert(index); } _ => {} } @@ -1121,7 +1120,7 @@ pub fn provide(providers: &mut Providers) { fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> (u8, Lrc>) { + -> (u8, Lrc>) { // NB: This `borrow()` is guaranteed to be valid (i.e., the value // cannot yet be stolen), because `mir_validated()`, which steals // from `mir_const(), forces this query to execute before @@ -1130,7 +1129,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if mir.return_ty().references_error() { tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors"); - return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSet::new_empty(0))); + return (Qualif::NOT_CONST.bits(), Lrc::new(BitSet::new_empty(0))); } let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const); @@ -1220,7 +1219,7 @@ fn run_pass<'a, 'tcx>(&self, block.statements.retain(|statement| { match statement.kind { StatementKind::StorageDead(index) => { - !promoted_temps.contains(&index) + !promoted_temps.contains(index) } _ => true } @@ -1228,7 +1227,7 @@ fn run_pass<'a, 'tcx>(&self, let terminator = block.terminator_mut(); match terminator.kind { TerminatorKind::Drop { location: Place::Local(index), target, .. } => { - if promoted_temps.contains(&index) { + if promoted_temps.contains(index) { terminator.kind = TerminatorKind::Goto { target, }; diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index a2561d3d793..9cdd94a7be7 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -10,7 +10,7 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use transform::{MirPass, MirSource}; use util::patch::MirPatch; @@ -45,7 +45,7 @@ fn is_nop_landing_pad( &self, bb: BasicBlock, mir: &Mir, - nop_landing_pads: &BitArray, + nop_landing_pads: &BitSet, ) -> bool { for stmt in &mir[bb].statements { match stmt.kind { @@ -111,7 +111,7 @@ fn remove_nop_landing_pads(&self, mir: &mut Mir) { let mut jumps_folded = 0; let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len()); + let mut nop_landing_pads = BitSet::new_empty(mir.basic_blocks().len()); // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index f3e0f557363..3c898eedebc 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,7 +14,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::bit_set::BitSet; use transform::{MirPass, MirSource}; use dataflow::{do_dataflow, DebugFormatted}; @@ -46,7 +46,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(mir, tcx).unwrap(); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &mdpe), @@ -175,7 +175,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Okay, our search is over. match move_data.rev_lookup.find(peeking_at_place) { LookupResult::Exact(peek_mpi) => { - let bit_state = sets.on_entry.contains(&peek_mpi); + let bit_state = sets.on_entry.contains(peek_mpi); debug!("rustc_peek({:?} = &{:?}) bit_state: {}", place, peeking_at_place, bit_state); if !bit_state { diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 164790db4b5..a6e0932bf0a 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -37,7 +37,7 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::ty::TyCtxt; use rustc::mir::*; @@ -249,7 +249,7 @@ fn strip_nops(&mut self) { } pub fn remove_dead_blocks(mir: &mut Mir) { - let mut seen = BitArray::new(mir.basic_blocks().len()); + let mut seen = BitSet::new_empty(mir.basic_blocks().len()); for (bb, _) in traversal::preorder(mir) { seen.insert(bb.index()); } @@ -285,7 +285,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { - let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) }; + let mut marker = DeclMarker { locals: BitSet::new_empty(mir.local_decls.len()) }; marker.visit_mir(mir); // Return pointer and arguments are always live marker.locals.insert(RETURN_PLACE); @@ -310,7 +310,7 @@ fn run_pass<'a, 'tcx>(&self, /// Construct the mapping while swapping out unused stuff out from the `vec`. fn make_local_map<'tcx, V>( vec: &mut IndexVec, - mask: BitArray, + mask: BitSet, ) -> IndexVec> { let mut map: IndexVec> = IndexVec::from_elem(None, &*vec); let mut used = Local::new(0); @@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>( } struct DeclMarker { - pub locals: BitArray, + pub locals: BitSet, } impl<'tcx> Visitor<'tcx> for DeclMarker { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 3ae470e1d4b..420ca4efde3 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -37,7 +37,7 @@ use rustc::mir::Local; use rustc::mir::*; use rustc::ty::{item_path, TyCtxt}; -use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; use std::fs; @@ -46,7 +46,7 @@ use transform::MirSource; use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; -pub type LiveVarSet = IdxSet; +pub type LiveVarSet = BitSet; /// This gives the result of the liveness analysis at the boundary of /// basic blocks. @@ -243,8 +243,8 @@ fn add_def(&mut self, index: V) { // X = 5 // // Defs = {}, Uses = {X} // use(X) - self.uses.remove(&index); - self.defs.add(&index); + self.uses.remove(index); + self.defs.insert(index); } fn add_use(&mut self, index: V) { @@ -258,8 +258,8 @@ fn add_use(&mut self, index: V) { // X = 5 // // Defs = {}, Uses = {X} // use(X) - self.defs.remove(&index); - self.uses.add(&index); + self.defs.remove(index); + self.uses.insert(index); } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2ee5415018f..f6ace57f5e0 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -182,8 +182,9 @@ fn while_if_let_ambiguity(&self, expr: &P) { ); if let Ok(snippet) = self.session.source_map().span_to_snippet(span) { - err.span_suggestion( + err.span_suggestion_with_applicability( span, "consider adding parentheses", format!("({})", snippet), + Applicability::MachineApplicable, ); } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 61c2ac161bb..a87e86aee0c 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -16,6 +16,7 @@ use rustc::hir::{self, Node, Destination}; use syntax::ast; use syntax_pos::Span; +use errors::Applicability; #[derive(Clone, Copy, Debug, PartialEq)] enum LoopKind { @@ -140,11 +141,16 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) { .span_label(e.span, "can only break with a value inside \ `loop` or breakable block") - .span_suggestion(e.span, - &format!("instead, use `break` on its own \ - without a value inside this `{}` loop", - kind.name()), - "break".to_string()) + .span_suggestion_with_applicability( + e.span, + &format!( + "instead, use `break` on its own \ + without a value inside this `{}` loop", + kind.name() + ), + "break".to_string(), + Applicability::MaybeIncorrect, + ) .emit(); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f0ff8c419fd..327eaacdf16 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -65,7 +65,6 @@ use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; -use syntax::feature_gate::{feature_err, GateIssue}; use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; @@ -1429,8 +1428,6 @@ pub struct Resolver<'a, 'b: 'a> { ambiguity_errors: Vec>, /// `use` injections are delayed for better placement and deduplication use_injections: Vec>, - /// `use` injections for proc macros wrongly imported with #[macro_use] - proc_mac_errors: Vec, /// crate-local macro expanded `macro_export` referred to by a module-relative path macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, @@ -1458,9 +1455,6 @@ pub struct Resolver<'a, 'b: 'a> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - /// A set of procedural macros imported by `#[macro_use]` that have already been warned about - warned_proc_macros: FxHashSet, - potentially_unused_imports: Vec<&'a ImportDirective<'a>>, /// This table maps struct IDs into struct constructor IDs, @@ -1471,9 +1465,6 @@ pub struct Resolver<'a, 'b: 'a> { current_type_ascription: Vec, injected_crate: Option>, - - /// Only supposed to be used by rustdoc, otherwise should be false. - pub ignore_extern_prelude_feature: bool, } /// Nothing really interesting here, it just provides memory for the rest of the crate. @@ -1674,13 +1665,14 @@ pub fn new(session: &'a Session, let mut extern_prelude: FxHashSet = session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(); - if !attr::contains_name(&krate.attrs, "no_core") { - if !attr::contains_name(&krate.attrs, "no_std") { - extern_prelude.insert(Symbol::intern("std")); - } else { - extern_prelude.insert(Symbol::intern("core")); - } - } + + // HACK(eddyb) this ignore the `no_{core,std}` attributes. + // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`. + // if !attr::contains_name(&krate.attrs, "no_core") { + // if !attr::contains_name(&krate.attrs, "no_std") { + extern_prelude.insert(Symbol::intern("core")); + extern_prelude.insert(Symbol::intern("std")); + extern_prelude.insert(Symbol::intern("meta")); let mut invocations = FxHashMap(); invocations.insert(Mark::root(), @@ -1743,7 +1735,6 @@ pub fn new(session: &'a Session, privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), use_injections: Vec::new(), - proc_mac_errors: Vec::new(), macro_expanded_macro_export_errors: BTreeSet::new(), arenas, @@ -1765,14 +1756,12 @@ pub fn new(session: &'a Session, local_macro_def_scopes: FxHashMap(), name_already_seen: FxHashMap(), whitelisted_legacy_custom_derives: Vec::new(), - warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), struct_constructors: DefIdMap(), found_unresolved_macro: false, unused_macros: FxHashSet(), current_type_ascription: Vec::new(), injected_crate: None, - ignore_extern_prelude_feature: false, } } @@ -1975,14 +1964,9 @@ fn resolve_ident_in_lexical_scope(&mut self, if !module.no_implicit_prelude { // `record_used` means that we don't try to load crates during speculative resolution if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) { - if !self.session.features_untracked().extern_prelude && - !self.ignore_extern_prelude_feature { - feature_err(&self.session.parse_sess, "extern_prelude", - ident.span, GateIssue::Language, - "access to extern crates through prelude is experimental").emit(); - } - - let crate_root = self.load_extern_prelude_crate_if_needed(ident); + let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); + let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(&crate_root); let binding = (crate_root, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); @@ -2010,13 +1994,6 @@ fn resolve_ident_in_lexical_scope(&mut self, None } - fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> { - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); - let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(&crate_root); - crate_root - } - fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span) -> Option> { if !module.expansion.is_descendant_of(span.ctxt().outer()) { @@ -3303,9 +3280,12 @@ fn type_ascription_suggestion(&self, err.span_label(base_span, "expecting a type here because of type ascription"); if line_sp != line_base_sp { - err.span_suggestion_short(sp, - "did you mean to use `;` here instead?", - ";".to_string()); + err.span_suggestion_short_with_applicability( + sp, + "did you mean to use `;` here instead?", + ";".to_string(), + Applicability::MaybeIncorrect, + ); } break; } else if snippet.trim().len() != 0 { @@ -3584,7 +3564,6 @@ fn resolve_path_with_parent_scope( } if name == keywords::Extern.name() || name == keywords::CrateRoot.name() && - self.session.features_untracked().extern_absolute_paths && self.session.rust_2018() { module = Some(ModuleOrUniformRoot::UniformRoot(name)); continue; @@ -3723,12 +3702,6 @@ fn lint_if_path_starts_with_module( return } - // In the 2015 edition there's no use in emitting lints unless the - // crate's already enabled the feature that we're going to suggest - if !self.session.features_untracked().crate_in_paths { - return - } - let (diag_id, diag_span) = match crate_lint { CrateLint::No => return, CrateLint::SimplePath(id) => (id, path_span), @@ -4425,17 +4398,26 @@ fn lookup_import_candidates(&mut self, ) ); - if self.session.features_untracked().extern_prelude { + if self.session.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); - for &krate_name in extern_prelude_names.iter() { - let krate_ident = Ident::with_empty_ctxt(krate_name); - let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident); + for &name in extern_prelude_names.iter() { + let ident = Ident::with_empty_ctxt(name); + match self.crate_loader.maybe_process_path_extern(name, ident.span) { + Some(crate_id) => { + let crate_root = self.get_module(DefId { + krate: crate_id, + index: CRATE_DEF_INDEX, + }); + self.populate_module_if_necessary(&crate_root); - suggestions.extend( - self.lookup_import_candidates_from_module( - lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn - ) - ); + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, crate_root, ident, &filter_fn + ) + ); + } + None => {} + } } } @@ -4597,7 +4579,6 @@ fn report_ambiguity_error(&self, ident: Ident, b1: &NameBinding, b2: &NameBindin fn report_errors(&mut self, krate: &Crate) { self.report_with_use_injections(krate); - self.report_proc_macro_import(krate); let mut reported_spans = FxHashSet(); for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { @@ -4821,7 +4802,12 @@ fn show_candidates(err: &mut DiagnosticBuilder, *candidate = format!("use {};\n{}", candidate, additional_newline); } - err.span_suggestions(span, &msg, path_strings); + err.span_suggestions_with_applicability( + span, + &msg, + path_strings, + Applicability::Unspecified, + ); } else { let mut msg = msg; msg.push(':'); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index d955a21ef23..35d96b9302b 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -19,13 +19,12 @@ use rustc::hir::def::{Def, NonMacroAttrKind}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; -use rustc::middle::cstore::CrateStore; use syntax::ast::{self, Name, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; -use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; +use syntax::ext::expand::{AstFragment, Invocation, InvocationKind, TogetherWith}; use syntax::ext::hygiene::{self, Mark}; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue}; @@ -110,14 +109,6 @@ pub struct ParentScope<'a> { crate derives: Vec, } -pub struct ProcMacError { - crate_name: Symbol, - name: Symbol, - module: ast::NodeId, - use_span: Span, - warn_msg: &'static str, -} - // Macro namespace is separated into two sub-namespaces, one for bang macros and // one for attribute-like macros (attributes, derives). // We ignore resolutions from one sub-namespace when searching names in scope for another. @@ -341,21 +332,30 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_deri fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result>, Determinacy> { - let (path, kind, derives_in_scope) = match invoc.kind { + let (path, kind, derives_in_scope, together_with) = match invoc.kind { InvocationKind::Attr { attr: None, .. } => return Ok(None), - InvocationKind::Attr { attr: Some(ref attr), ref traits, .. } => - (&attr.path, MacroKind::Attr, traits.clone()), + InvocationKind::Attr { attr: Some(ref attr), ref traits, together_with, .. } => + (&attr.path, MacroKind::Attr, traits.clone(), together_with), InvocationKind::Bang { ref mac, .. } => - (&mac.node.path, MacroKind::Bang, Vec::new()), + (&mac.node.path, MacroKind::Bang, Vec::new(), TogetherWith::None), InvocationKind::Derive { ref path, .. } => - (path, MacroKind::Derive, Vec::new()), + (path, MacroKind::Derive, Vec::new(), TogetherWith::None), }; let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?; if let Def::Macro(def_id, _) = def { + match together_with { + TogetherWith::Derive => + self.session.span_err(invoc.span(), + "macro attributes must be placed before `#[derive]`"), + TogetherWith::TestBench if !self.session.features_untracked().plugin => + self.session.span_err(invoc.span(), + "macro attributes cannot be used together with `#[test]` or `#[bench]`"), + _ => {} + } self.macro_defs.insert(invoc.expansion_data.mark, def_id); let normal_module_def_id = self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; @@ -682,14 +682,6 @@ enum WhereToResolve<'a> { } WhereToResolve::ExternPrelude => { if use_prelude && self.extern_prelude.contains(&ident.name) { - if !self.session.features_untracked().extern_prelude && - !self.ignore_extern_prelude_feature { - feature_err(&self.session.parse_sess, "extern_prelude", - ident.span, GateIssue::Language, - "access to extern crates through prelude is experimental") - .emit(); - } - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); let crate_root = @@ -980,7 +972,6 @@ pub fn finalize_current_module_macro_resolutions(&mut self) { check_consistency(self, binding.def_ignoring_ambiguity()); if from_prelude { self.record_use(ident, MacroNS, binding); - self.err_if_macro_use_proc_macro(ident.name, span, binding); } } }; @@ -1132,69 +1123,6 @@ pub fn define_macro(&mut self, } } - /// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]` - fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span, - binding: &NameBinding<'a>) { - let krate = match binding.def() { - Def::NonMacroAttr(..) | Def::Err => return, - Def::Macro(def_id, _) => def_id.krate, - _ => unreachable!(), - }; - - // Plugin-based syntax extensions are exempt from this check - if krate == CrateNum::BuiltinMacros { return; } - - let ext = binding.get_macro(self); - - match *ext { - // If `ext` is a procedural macro, check if we've already warned about it - SyntaxExtension::AttrProcMacro(..) | SyntaxExtension::ProcMacro { .. } => - if !self.warned_proc_macros.insert(name) { return; }, - _ => return, - } - - let warn_msg = match *ext { - SyntaxExtension::AttrProcMacro(..) => - "attribute procedural macros cannot be imported with `#[macro_use]`", - SyntaxExtension::ProcMacro { .. } => - "procedural macros cannot be imported with `#[macro_use]`", - _ => return, - }; - - let def_id = self.current_module.normal_ancestor_id; - let node_id = self.definitions.as_local_node_id(def_id).unwrap(); - - self.proc_mac_errors.push(ProcMacError { - crate_name: self.cstore.crate_name_untracked(krate), - name, - module: node_id, - use_span, - warn_msg, - }); - } - - pub fn report_proc_macro_import(&mut self, krate: &ast::Crate) { - for err in self.proc_mac_errors.drain(..) { - let (span, found_use) = ::UsePlacementFinder::check(krate, err.module); - - if let Some(span) = span { - let found_use = if found_use { "" } else { "\n" }; - self.session.struct_span_err(err.use_span, err.warn_msg) - .span_suggestion_with_applicability( - span, - "instead, import the procedural macro like any other item", - format!("use {}::{};{}", err.crate_name, err.name, found_use), - Applicability::MachineApplicable - ).emit(); - } else { - self.session.struct_span_err(err.use_span, err.warn_msg) - .help(&format!("instead, import the procedural macro like any other item: \ - `use {}::{};`", err.crate_name, err.name)) - .emit(); - } - } - } - fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { if !self.session.features_untracked().custom_derive { let sess = &self.session.parse_sess; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e7d3a8ef661..dc4a76db692 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -196,7 +196,11 @@ pub fn resolve_ident_in_module_unadjusted(&mut self, } // Fall back to resolving to an external crate. - if !(ns == TypeNS && self.extern_prelude.contains(&ident.name)) { + if !( + ns == TypeNS && + !ident.is_path_segment_keyword() && + self.extern_prelude.contains(&ident.name) + ) { // ... unless the crate name is not in the `extern_prelude`. return binding; } @@ -211,7 +215,11 @@ pub fn resolve_ident_in_module_unadjusted(&mut self, ) { self.resolve_crate_root(ident) - } else if ns == TypeNS && !ident.is_path_segment_keyword() { + } else if + ns == TypeNS && + !ident.is_path_segment_keyword() && + self.extern_prelude.contains(&ident.name) + { let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) @@ -738,7 +746,7 @@ struct UniformPathsCanaryResults<'a> { // Currently imports can't resolve in non-module scopes, // we only have canaries in them for future-proofing. if external_crate.is_none() && results.module_scope.is_none() { - return; + continue; } { @@ -753,7 +761,7 @@ struct UniformPathsCanaryResults<'a> { let possible_resultions = 1 + all_results.filter(|&def| def != first).count(); if possible_resultions <= 1 { - return; + continue; } } diff --git a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs index 8747f239d34..c71ad5ff21d 100644 --- a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs +++ b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor}; +use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy}; pub fn target() -> TargetResult { let mut base = super::windows_msvc_base::opts(); @@ -17,7 +17,6 @@ pub fn target() -> TargetResult { // FIXME: this shouldn't be panic=abort, it should be panic=unwind base.panic_strategy = PanicStrategy::Abort; - base.linker = Some("rust-lld".to_owned()); Ok(Target { llvm_target: "aarch64-pc-windows-msvc".to_string(), @@ -29,7 +28,7 @@ pub fn target() -> TargetResult { target_os: "windows".to_string(), target_env: "msvc".to_string(), target_vendor: "pc".to_string(), - linker_flavor: LinkerFlavor::Lld(LldFlavor::Link), + linker_flavor: LinkerFlavor::Msvc, options: base, }) } diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index 7fe1af81951..a6618efebb3 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -11,9 +11,9 @@ //! New recursive solver modeled on Chalk's recursive solver. Most of //! the guts are broken up into modules; see the comments in those modules. -#![feature(crate_in_paths)] +#![cfg_attr(stage0, feature(crate_in_paths))] #![feature(crate_visibility_modifier)] -#![feature(extern_prelude)] +#![cfg_attr(stage0, feature(extern_prelude))] #![feature(in_band_lifetimes)] #![cfg_attr(not(stage0), feature(nll))] diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index ebe0c279aaf..85641854e6e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -40,7 +40,7 @@ use super::FnCtxt; -use errors::DiagnosticBuilder; +use errors::{DiagnosticBuilder,Applicability}; use hir::def_id::DefId; use lint; use rustc::hir; @@ -299,9 +299,12 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) { err.note("The type information given here is insufficient to check whether \ the pointer cast is valid"); if unknown_cast_to { - err.span_suggestion_short(self.cast_span, - "consider giving more type information", - String::new()); + err.span_suggestion_short_with_applicability( + self.cast_span, + "consider giving more type information", + String::new(), + Applicability::Unspecified, + ); } err.emit(); } @@ -327,9 +330,12 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { if self.cast_ty.is_trait() { match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { Ok(s) => { - err.span_suggestion(self.cast_span, - "try casting to a reference instead", - format!("&{}{}", mtstr, s)); + err.span_suggestion_with_applicability( + self.cast_span, + "try casting to a reference instead", + format!("&{}{}", mtstr, s), + Applicability::MachineApplicable, + ); } Err(_) => { span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr) @@ -346,9 +352,12 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { ty::Adt(def, ..) if def.is_box() => { match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { Ok(s) => { - err.span_suggestion(self.cast_span, - "try casting to a `Box` instead", - format!("Box<{}>", s)); + err.span_suggestion_with_applicability( + self.cast_span, + "try casting to a `Box` instead", + format!("Box<{}>", s), + Applicability::MachineApplicable, + ); } Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr), } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index a283e032e0e..f2c20238734 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -504,7 +504,7 @@ fn sig_of_closure_with_mismatched_number_of_arguments( .sig .inputs() .iter() - .map(|ty| ArgKind::from_expected_ty(ty)) + .map(|ty| ArgKind::from_expected_ty(ty, None)) .collect(); let (closure_span, found_args) = self.get_fn_like_arguments(expr_map_node); let expected_span = expected_sig.cause_span.unwrap_or(closure_span); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 9aa2ba363ed..a192068d28f 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -16,6 +16,7 @@ use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{Subst, Substs}; use rustc::util::common::ErrorReported; +use errors::Applicability; use syntax_pos::Span; @@ -321,10 +322,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(trait_err_span) = trait_err_span { if let Ok(trait_err_str) = tcx.sess.source_map(). span_to_snippet(trait_err_span) { - diag.span_suggestion( + diag.span_suggestion_with_applicability( impl_err_span, "consider change the type to match the mutability in trait", format!("{}", trait_err_str), + Applicability::MachineApplicable, ); } } @@ -799,7 +801,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .span_to_snippet(trait_m.generics.span) .ok()?; - err.multipart_suggestion( + err.multipart_suggestion_with_applicability( "try changing the `impl Trait` argument to a generic parameter", vec![ // replace `impl Trait` with `T` @@ -809,6 +811,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // of the generics, but it works for the common case (generics_span, new_generics), ], + Applicability::MaybeIncorrect, ); Some(()) })(); @@ -870,7 +873,7 @@ fn nested_visit_map<'this>( .span_to_snippet(bounds) .ok()?; - err.multipart_suggestion( + err.multipart_suggestion_with_applicability( "try removing the generic parameter and using `impl Trait` instead", vec![ // delete generic parameters @@ -878,6 +881,7 @@ fn nested_visit_map<'this>( // replace param usage with `impl Trait` (span, format!("impl {}", bounds)), ], + Applicability::MaybeIncorrect, ); Some(()) })(); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 4e22ead8db9..ee19574dc4e 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -132,9 +132,12 @@ pub fn demand_coerce_diag(&self, let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr)); let suggestions = compatible_variants.iter() .map(|v| format!("{}({})", v, expr_text)).collect::>(); - err.span_suggestions(expr.span, - "try using a variant of the expected type", - suggestions); + err.span_suggestions_with_applicability( + expr.span, + "try using a variant of the expected type", + suggestions, + Applicability::MaybeIncorrect, + ); } } @@ -415,10 +418,55 @@ pub fn check_for_cast(&self, src, if needs_paren { ")" } else { "" }, expected_ty); - let into_suggestion = format!("{}{}{}.into()", - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }); + let into_suggestion = format!( + "{}{}{}.into()", + if needs_paren { "(" } else { "" }, + src, + if needs_paren { ")" } else { "" }, + ); + let literal_is_ty_suffixed = |expr: &hir::Expr| { + if let hir::ExprKind::Lit(lit) = &expr.node { + lit.node.is_suffixed() + } else { + false + } + }; + + let into_sugg = into_suggestion.clone(); + let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder, + note: Option<&str>| { + let suggest_msg = if literal_is_ty_suffixed(expr) { + format!( + "change the type of the numeric literal from `{}` to `{}`", + checked_ty, + expected_ty, + ) + } else { + match note { + Some(note) => format!("{}, which {}", msg, note), + _ => format!("{} in a lossless way", msg), + } + }; + + let suffix_suggestion = format!( + "{}{}{}{}", + if needs_paren { "(" } else { "" }, + src.trim_right_matches(&checked_ty.to_string()), + expected_ty, + if needs_paren { ")" } else { "" }, + ); + + err.span_suggestion_with_applicability( + expr.span, + &suggest_msg, + if literal_is_ty_suffixed(expr) { + suffix_suggestion + } else { + into_sugg + }, + Applicability::MachineApplicable, + ); + }; match (&expected_ty.sty, &checked_ty.sty) { (&ty::Int(ref exp), &ty::Int(ref found)) => { @@ -444,11 +492,9 @@ pub fn check_for_cast(&self, } } _ => { - err.span_suggestion_with_applicability( - expr.span, - &format!("{}, which {}", msg, will_sign_extend), - into_suggestion, - Applicability::MachineApplicable + suggest_to_change_suffix_or_into( + err, + Some(will_sign_extend), ); } } @@ -477,12 +523,10 @@ pub fn check_for_cast(&self, } } _ => { - err.span_suggestion_with_applicability( - expr.span, - &format!("{}, which {}", msg, will_zero_extend), - into_suggestion, - Applicability::MachineApplicable - ); + suggest_to_change_suffix_or_into( + err, + Some(will_zero_extend), + ); } } true @@ -583,12 +627,10 @@ pub fn check_for_cast(&self, } (&ty::Float(ref exp), &ty::Float(ref found)) => { if found.bit_width() < exp.bit_width() { - err.span_suggestion_with_applicability( - expr.span, - &format!("{} in a lossless way", msg), - into_suggestion, - Applicability::MachineApplicable - ); + suggest_to_change_suffix_or_into( + err, + None, + ); } else if can_cast { err.span_suggestion_with_applicability( expr.span, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 85a437283fa..499daccf5e8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1064,7 +1064,8 @@ fn emit_unstable_name_collision_hint( "a method with this name may be added to the standard library in the future", ); - // FIXME: This should be a `span_suggestion` instead of `help`. However `self.span` only + // FIXME: This should be a `span_suggestion_with_applicability` instead of `help` + // However `self.span` only // highlights the method name, so we can't use it. Also consider reusing the code from // `report_method_error()`. diag.help(&format!( diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index abc32ed2ea0..fe5128a6958 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -251,13 +251,16 @@ pub fn report_method_error(&self, let snippet = tcx.sess.source_map().span_to_snippet(lit.span) .unwrap_or("".to_string()); - err.span_suggestion(lit.span, + err.span_suggestion_with_applicability( + lit.span, &format!("you must specify a concrete type for \ this numeric value, like `{}`", concrete_type), format!("{}_{}", snippet, - concrete_type)); + concrete_type), + Applicability::MaybeIncorrect, + ); } hir::ExprKind::Path(ref qpath) => { // local binding if let &hir::QPath::Resolved(_, ref path) = &qpath { @@ -281,13 +284,14 @@ pub fn report_method_error(&self, ty, .. })) => { - err.span_suggestion( + err.span_suggestion_with_applicability( // account for `let x: _ = 42;` // ^^^^ span.to(ty.as_ref().map(|ty| ty.span) .unwrap_or(span)), &msg, format!("{}: {}", snippet, concrete_type), + Applicability::MaybeIncorrect, ); } _ => { @@ -516,7 +520,12 @@ fn suggest_use_candidates(&self, format!("use {};\n{}", self.tcx.item_path_str(*did), additional_newline) }).collect(); - err.span_suggestions(span, &msg, path_strings); + err.span_suggestions_with_applicability( + span, + &msg, + path_strings, + Applicability::MaybeIncorrect, + ); } else { let limit = if candidates.len() == 5 { 5 } else { 4 }; for (i, trait_did) in candidates.iter().take(limit).enumerate() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index aa27fe528e1..0dc7bc75c3d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -622,7 +622,10 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self { let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id)); let implicit_region_bound = body_id.map(|body_id| { let body = tcx.hir.body(body_id); - tcx.mk_region(ty::ReScope(region::Scope::CallSite(body.value.hir_id.local_id))) + tcx.mk_region(ty::ReScope(region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + })) }); Inherited { @@ -3344,11 +3347,34 @@ fn check_field(&self, } }; } + ty::Array(_, len) => { + if let (Some(len), Ok(user_index)) = ( + len.assert_usize(self.tcx), + field.as_str().parse::() + ) { + let base = self.tcx.hir.node_to_pretty_string(base.id); + let help = "instead of using tuple indexing, use array indexing"; + let suggestion = format!("{}[{}]", base, field); + let applicability = if len < user_index { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + err.span_suggestion_with_applicability( + expr.span, help, suggestion, applicability + ); + } + } ty::RawPtr(..) => { let base = self.tcx.hir.node_to_pretty_string(base.id); let msg = format!("`{}` is a native pointer; try dereferencing it", base); let suggestion = format!("(*{}).{}", base, field); - err.span_suggestion(field.span, &msg, suggestion); + err.span_suggestion_with_applicability( + field.span, + &msg, + suggestion, + Applicability::MaybeIncorrect, + ); } _ => {} } @@ -4716,7 +4742,12 @@ pub fn suggest_ref_or_into( found: Ty<'tcx>, ) { if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) { - err.span_suggestion(sp, msg, suggestion); + err.span_suggestion_with_applicability( + sp, + msg, + suggestion, + Applicability::MachineApplicable, + ); } else if !self.check_for_cast(err, expr, found, expected) { let methods = self.get_conversion_methods(expr.span, expected, found); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { @@ -4746,7 +4777,12 @@ pub fn suggest_ref_or_into( } }) .collect::>(); if !suggestions.is_empty() { - err.span_suggestions(expr.span, "try using a conversion method", suggestions); + err.span_suggestions_with_applicability( + expr.span, + "try using a conversion method", + suggestions, + Applicability::MaybeIncorrect, + ); } } } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 5004880ce47..5969f288d73 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -16,7 +16,7 @@ use rustc::ty::TyKind::{Ref, Adt, Str, Uint, Never, Tuple, Char, Array}; use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::infer::type_variable::TypeVariableOrigin; -use errors; +use errors::{self,Applicability}; use syntax_pos::Span; use syntax::ast::Ident; use rustc::hir; @@ -444,9 +444,12 @@ fn check_str_addition( err.span_label(expr.span, "`+` can't be used to concatenate two `&str` strings"); match source_map.span_to_snippet(lhs_expr.span) { - Ok(lstring) => err.span_suggestion(lhs_expr.span, - msg, - format!("{}.to_owned()", lstring)), + Ok(lstring) => err.span_suggestion_with_applicability( + lhs_expr.span, + msg, + format!("{}.to_owned()", lstring), + Applicability::MachineApplicable, + ), _ => err.help(msg), }; } @@ -462,10 +465,14 @@ fn check_str_addition( is_assign, ) { (Ok(l), Ok(r), false) => { - err.multipart_suggestion(msg, vec![ - (lhs_expr.span, format!("{}.to_owned()", l)), - (rhs_expr.span, format!("&{}", r)), - ]); + err.multipart_suggestion_with_applicability( + msg, + vec![ + (lhs_expr.span, format!("{}.to_owned()", l)), + (rhs_expr.span, format!("&{}", r)), + ], + Applicability::MachineApplicable, + ); } _ => { err.help(msg); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 05fe0cb9262..fbf8afc3be2 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -307,7 +307,10 @@ fn visit_fn_body(&mut self, let body_id = body.id(); self.body_id = body_id.node_id; - let call_site = region::Scope::CallSite(body.value.hir_id.local_id); + let call_site = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + }; self.call_site_scope = Some(call_site); let fn_sig = { @@ -333,7 +336,12 @@ fn visit_fn_body(&mut self, &fn_sig_tys[..], body_id.node_id, span); - self.link_fn_args(region::Scope::Node(body.value.hir_id.local_id), &body.arguments); + self.link_fn_args( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node + }, + &body.arguments); self.visit_body(body); self.visit_region_obligations(body_id.node_id); @@ -483,7 +491,10 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) { let expr_ty = self.resolve_node_type(expr.hir_id); // the region corresponding to this expression let expr_region = self.tcx.mk_region(ty::ReScope( - region::Scope::Node(expr.hir_id.local_id))); + region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span), expr_ty, expr_region); @@ -766,7 +777,10 @@ fn constrain_call<'b, I: Iterator>(&mut self, // call occurs. // // FIXME(#6268) to support nested method calls, should be callee_id - let callee_scope = region::Scope::Node(call_expr.hir_id.local_id); + let callee_scope = region::Scope { + id: call_expr.hir_id.local_id, + data: region::ScopeData::Node + }; let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope)); debug!("callee_region={:?}", callee_region); @@ -819,7 +833,10 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult { @@ -1072,7 +1092,10 @@ fn link_autoref(&self, } adjustment::AutoBorrow::RawPtr(m) => { - let r = self.tcx.mk_region(ty::ReScope(region::Scope::Node(expr.hir_id.local_id))); + let r = self.tcx.mk_region(ty::ReScope(region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } } diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e163fc68cbd..845bfad7807 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -11,3 +11,4 @@ path = "lib.rs" pulldown-cmark = { version = "0.1.2", default-features = false } minifier = "0.0.19" tempfile = "3" +parking_lot = "0.6.4" diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index e7e371cd567..34c4c70159f 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -69,7 +69,7 @@ pub fn get_blanket_impls( let real_name = name.clone().map(|name| Ident::from_str(&name)); let param_env = self.cx.tcx.param_env(def_id); for &trait_def_id in self.cx.all_traits.iter() { - if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) || + if !self.cx.renderinfo.borrow().access_levels.is_doc_reachable(trait_def_id) || self.cx.generated_synthetics .borrow_mut() .get(&(def_id, trait_def_id)) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 507461f2ea1..1ea130cf16a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -29,8 +29,6 @@ self, GetDefId, ToSource, - get_auto_traits_with_def_id, - get_blanket_impls_with_def_id, }; use super::Clean; @@ -56,7 +54,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa let inner = match def { Def::Trait(did) => { record_extern_fqn(cx, did, clean::TypeKind::Trait); - ret.extend(build_impls(cx, did, false)); + ret.extend(build_impls(cx, did)); clean::TraitItem(build_external_trait(cx, did)) } Def::Fn(did) => { @@ -65,27 +63,27 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa } Def::Struct(did) => { record_extern_fqn(cx, did, clean::TypeKind::Struct); - ret.extend(build_impls(cx, did, true)); + ret.extend(build_impls(cx, did)); clean::StructItem(build_struct(cx, did)) } Def::Union(did) => { record_extern_fqn(cx, did, clean::TypeKind::Union); - ret.extend(build_impls(cx, did, true)); + ret.extend(build_impls(cx, did)); clean::UnionItem(build_union(cx, did)) } Def::TyAlias(did) => { record_extern_fqn(cx, did, clean::TypeKind::Typedef); - ret.extend(build_impls(cx, did, false)); + ret.extend(build_impls(cx, did)); clean::TypedefItem(build_type_alias(cx, did), false) } Def::Enum(did) => { record_extern_fqn(cx, did, clean::TypeKind::Enum); - ret.extend(build_impls(cx, did, true)); + ret.extend(build_impls(cx, did)); clean::EnumItem(build_enum(cx, did)) } Def::ForeignTy(did) => { record_extern_fqn(cx, did, clean::TypeKind::Foreign); - ret.extend(build_impls(cx, did, false)); + ret.extend(build_impls(cx, did)); clean::ForeignTypeItem } // Never inline enum variants but leave them shown as re-exports. @@ -159,12 +157,11 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes { /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { + let mut crate_name = cx.tcx.crate_name(did.krate).to_string(); if did.is_local() { - debug!("record_extern_fqn(did={:?}, kind+{:?}): def_id is local, aborting", did, kind); - return; + crate_name = cx.crate_name.clone().unwrap_or(crate_name); } - let crate_name = cx.tcx.crate_name(did.krate).to_string(); let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| { // extern blocks have an empty name let s = elem.data.to_string(); @@ -179,7 +176,12 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { } else { once(crate_name).chain(relative).collect() }; - cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind)); + + if did.is_local() { + cx.renderinfo.borrow_mut().exact_paths.insert(did, fqn); + } else { + cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind)); + } } pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { @@ -271,7 +273,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef { } } -pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec { +pub fn build_impls(cx: &DocContext, did: DefId) -> Vec { let tcx = cx.tcx; let mut impls = Vec::new(); @@ -279,85 +281,6 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec = auto_impls.into_iter() - .filter(|i| renderinfo.inlined.insert(i.def_id)).collect(); - - impls.extend(new_impls); - } - impls.extend(get_blanket_impls_with_def_id(cx, did)); - } - - // If this is the first time we've inlined something from another crate, then - // we inline *all* impls from all the crates into this crate. Note that there's - // currently no way for us to filter this based on type, and we likely need - // many impls for a variety of reasons. - // - // Primarily, the impls will be used to populate the documentation for this - // type being inlined, but impls can also be used when generating - // documentation for primitives (no way to find those specifically). - if cx.populated_all_crate_impls.get() { - return impls; - } - - cx.populated_all_crate_impls.set(true); - - for &cnum in tcx.crates().iter() { - for did in tcx.all_trait_implementations(cnum).iter() { - build_impl(cx, *did, &mut impls); - } - } - - // Also try to inline primitive impls from other crates. - let lang_items = tcx.lang_items(); - let primitive_impls = [ - lang_items.isize_impl(), - lang_items.i8_impl(), - lang_items.i16_impl(), - lang_items.i32_impl(), - lang_items.i64_impl(), - lang_items.i128_impl(), - lang_items.usize_impl(), - lang_items.u8_impl(), - lang_items.u16_impl(), - lang_items.u32_impl(), - lang_items.u64_impl(), - lang_items.u128_impl(), - lang_items.f32_impl(), - lang_items.f64_impl(), - lang_items.f32_runtime_impl(), - lang_items.f64_runtime_impl(), - lang_items.char_impl(), - lang_items.str_impl(), - lang_items.slice_impl(), - lang_items.slice_u8_impl(), - lang_items.str_alloc_impl(), - lang_items.slice_alloc_impl(), - lang_items.slice_u8_alloc_impl(), - lang_items.const_ptr_impl(), - lang_items.mut_ptr_impl(), - ]; - - for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { - if !def_id.is_local() { - build_impl(cx, def_id, &mut impls); - - let auto_impls = get_auto_traits_with_def_id(cx, def_id); - let blanket_impls = get_blanket_impls_with_def_id(cx, def_id); - let mut renderinfo = cx.renderinfo.borrow_mut(); - - let new_impls: Vec = auto_impls.into_iter() - .chain(blanket_impls.into_iter()) - .filter(|i| renderinfo.inlined.insert(i.def_id)) - .collect(); - - impls.extend(new_impls); - } - } - impls } @@ -372,30 +295,60 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation - if let Some(traitref) = associated_trait { - if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { - return + if !did.is_local() { + if let Some(traitref) = associated_trait { + if !cx.renderinfo.borrow().access_levels.is_doc_reachable(traitref.def_id) { + return + } } } - let for_ = tcx.type_of(did).clean(cx); + let for_ = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { + match tcx.hir.expect_item(nodeid).node { + hir::ItemKind::Impl(.., ref t, _) => { + t.clean(cx) + } + _ => panic!("did given to build_impl was not an impl"), + } + } else { + tcx.type_of(did).clean(cx) + }; // Only inline impl if the implementing type is // reachable in rustdoc generated documentation - if let Some(did) = for_.def_id() { - if !cx.access_levels.borrow().is_doc_reachable(did) { - return + if !did.is_local() { + if let Some(did) = for_.def_id() { + if !cx.renderinfo.borrow().access_levels.is_doc_reachable(did) { + return + } } } let predicates = tcx.predicates_of(did); - let trait_items = tcx.associated_items(did).filter_map(|item| { - if associated_trait.is_some() || item.vis == ty::Visibility::Public { - Some(item.clean(cx)) - } else { - None + let (trait_items, generics) = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { + match tcx.hir.expect_item(nodeid).node { + hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => { + ( + item_ids.iter() + .map(|ii| tcx.hir.impl_item(ii.id).clean(cx)) + .collect::>(), + gen.clean(cx), + ) + } + _ => panic!("did given to build_impl was not an impl"), } - }).collect::>(); + } else { + ( + tcx.associated_items(did).filter_map(|item| { + if associated_trait.is_some() || item.vis == ty::Visibility::Public { + Some(item.clean(cx)) + } else { + None + } + }).collect::>(), + (tcx.generics_of(did), &predicates).clean(cx), + ) + }; let polarity = tcx.impl_polarity(did); let trait_ = associated_trait.clean(cx).map(|bound| { match bound { @@ -417,10 +370,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { .collect() }).unwrap_or(FxHashSet()); + debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); + ret.push(clean::Item { inner: clean::ImplItem(clean::Impl { unsafety: hir::Unsafety::Normal, - generics: (tcx.generics_of(did), &predicates).clean(cx), + generics, provided_trait_methods: provided, trait_, for_, @@ -465,7 +420,11 @@ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec, } pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String { - cx.tcx.rendered_const(did) + if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) { + cx.tcx.hir.node_to_pretty_string(node_id) + } else { + cx.tcx.rendered_const(did) + } } fn build_const(cx: &DocContext, did: DefId) -> clean::Constant { @@ -576,16 +535,27 @@ fn separate_supertrait_bounds(mut g: clean::Generics) } pub fn record_extern_trait(cx: &DocContext, did: DefId) { - if cx.external_traits.borrow().contains_key(&did) || - cx.active_extern_traits.borrow().contains(&did) - { + if did.is_local() { return; } + { + let external_traits = cx.external_traits.lock(); + if external_traits.borrow().contains_key(&did) || + cx.active_extern_traits.borrow().contains(&did) + { + return; + } + } + cx.active_extern_traits.borrow_mut().push(did); + debug!("record_extern_trait: {:?}", did); let trait_ = build_external_trait(cx, did); - cx.external_traits.borrow_mut().insert(did, trait_); + { + let external_traits = cx.external_traits.lock(); + external_traits.borrow_mut().insert(did, trait_); + } cx.active_extern_traits.borrow_mut().remove_item(&did); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 20b17afeab2..a982933f6c1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -28,7 +28,6 @@ use syntax_pos::{self, DUMMY_SP, Pos, FileName}; use rustc::mir::interpret::ConstValue; -use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime as rl; use rustc::ty::fold::TypeFolder; use rustc::middle::lang_items; @@ -56,6 +55,8 @@ use std::sync::Arc; use std::u32; +use parking_lot::ReentrantMutex; + use core::{self, DocContext}; use doctree; use visit_ast; @@ -135,10 +136,9 @@ pub struct Crate { pub module: Option, pub externs: Vec<(CrateNum, ExternalCrate)>, pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, - pub access_levels: Arc>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. - pub external_traits: FxHashMap, + pub external_traits: Arc>>>, pub masked_crates: FxHashSet, } @@ -209,9 +209,6 @@ fn clean(&self, cx: &DocContext) -> Crate { })); } - let mut access_levels = cx.access_levels.borrow_mut(); - let mut external_traits = cx.external_traits.borrow_mut(); - Crate { name, version: None, @@ -219,8 +216,7 @@ fn clean(&self, cx: &DocContext) -> Crate { module: Some(module), externs, primitives, - access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())), - external_traits: mem::replace(&mut external_traits, Default::default()), + external_traits: cx.external_traits.clone(), masked_crates, } } @@ -579,9 +575,9 @@ fn clean(&self, cx: &DocContext) -> Item { let mut items: Vec = vec![]; items.extend(self.extern_crates.iter().map(|x| x.clean(cx))); items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); - items.extend(self.structs.iter().flat_map(|x| x.clean(cx))); - items.extend(self.unions.iter().flat_map(|x| x.clean(cx))); - items.extend(self.enums.iter().flat_map(|x| x.clean(cx))); + items.extend(self.structs.iter().map(|x| x.clean(cx))); + items.extend(self.unions.iter().map(|x| x.clean(cx))); + items.extend(self.enums.iter().map(|x| x.clean(cx))); items.extend(self.fns.iter().map(|x| x.clean(cx))); items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); @@ -2436,7 +2432,7 @@ fn clean(&self, cx: &DocContext) -> Type { if let Def::TyAlias(def_id) = path.def { // Substitute private type aliases if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) { - if !cx.access_levels.borrow().is_exported(def_id) { + if !cx.renderinfo.borrow().access_levels.is_exported(def_id) { alias = Some(&cx.tcx.hir.expect_item(node_id).node); } } @@ -2816,14 +2812,10 @@ pub struct Union { pub fields_stripped: bool, } -impl Clean> for doctree::Struct { - fn clean(&self, cx: &DocContext) -> Vec { - let name = self.name.clean(cx); - let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); - ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - - ret.push(Item { - name: Some(name), +impl Clean for doctree::Struct { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), @@ -2836,20 +2828,14 @@ fn clean(&self, cx: &DocContext) -> Vec { fields: self.fields.clean(cx), fields_stripped: false, }), - }); - - ret + } } } -impl Clean> for doctree::Union { - fn clean(&self, cx: &DocContext) -> Vec { - let name = self.name.clean(cx); - let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); - ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - - ret.push(Item { - name: Some(name), +impl Clean for doctree::Union { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), @@ -2862,9 +2848,7 @@ fn clean(&self, cx: &DocContext) -> Vec { fields: self.fields.clean(cx), fields_stripped: false, }), - }); - - ret + } } } @@ -2895,14 +2879,10 @@ pub struct Enum { pub variants_stripped: bool, } -impl Clean> for doctree::Enum { - fn clean(&self, cx: &DocContext) -> Vec { - let name = self.name.clean(cx); - let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); - ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - - ret.push(Item { - name: Some(name), +impl Clean for doctree::Enum { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), @@ -2914,9 +2894,7 @@ fn clean(&self, cx: &DocContext) -> Vec { generics: self.generics.clean(cx), variants_stripped: false, }), - }); - - ret + } } } @@ -3445,11 +3423,7 @@ fn build_deref_target_impls(cx: &DocContext, let primitive = match *target { ResolvedPath { did, .. } if did.is_local() => continue, ResolvedPath { did, .. } => { - // We set the last parameter to false to avoid looking for auto-impls for traits - // and therefore avoid an ICE. - // The reason behind this is that auto-traits don't propagate through Deref so - // we're not supposed to synthesise impls for them. - ret.extend(inline::build_impls(cx, did, false)); + ret.extend(inline::build_impls(cx, did)); continue } _ => match target.primitive_type() { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a312913a69c..093788d2095 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -26,7 +26,7 @@ use rustc_metadata::cstore::CStore; use rustc_target::spec::TargetTriple; -use syntax::ast::{self, Ident}; +use syntax::ast::{self, Ident, NodeId}; use syntax::source_map; use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; @@ -36,11 +36,13 @@ use syntax_pos::DUMMY_SP; use errors; use errors::emitter::{Emitter, EmitterWriter}; +use parking_lot::ReentrantMutex; -use std::cell::{RefCell, Cell}; +use std::cell::RefCell; use std::mem; use rustc_data_structures::sync::{self, Lrc}; use std::rc::Rc; +use std::sync::Arc; use std::path::PathBuf; use visit_ast::RustdocVisitor; @@ -60,16 +62,13 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { /// The stack of module NodeIds up till this point pub crate_name: Option, pub cstore: Rc, - pub populated_all_crate_impls: Cell, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing // the access levels from crateanalysis. - /// Later on moved into `clean::Crate` - pub access_levels: RefCell>, /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` - pub external_traits: RefCell>, + pub external_traits: Arc>>>, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. pub active_extern_traits: RefCell>, @@ -164,6 +163,16 @@ pub fn next_def_id(&self, crate_num: CrateNum) -> DefId { def_id.clone() } + /// Like the function of the same name on the HIR map, but skips calling it on fake DefIds. + /// (This avoids a slice-index-out-of-bounds panic.) + pub fn as_local_node_id(&self, def_id: DefId) -> Option { + if self.all_fake_def_ids.borrow().contains(&def_id) { + None + } else { + self.tcx.hir.as_local_node_id(def_id) + } + } + pub fn get_real_ty(&self, def_id: DefId, def_ctor: &F, @@ -260,9 +269,10 @@ fn is_doc_reachable(&self, did: DefId) -> bool { /// /// If the given `error_format` is `ErrorOutputType::Json` and no `SourceMap` is given, a new one /// will be created for the handler. -pub fn new_handler(error_format: ErrorOutputType, source_map: Option>) - -> errors::Handler -{ +pub fn new_handler(error_format: ErrorOutputType, + source_map: Option>, + treat_err_as_bug: bool, +) -> errors::Handler { // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so // stick to the defaults let sessopts = Options::default(); @@ -299,7 +309,7 @@ pub fn new_handler(error_format: ErrorOutputType, source_map: Option, describe_lints: bool, mut manual_passes: Vec, - mut default_passes: passes::DefaultPassOption) - -> (clean::Crate, RenderInfo, Vec) -{ + mut default_passes: passes::DefaultPassOption, + treat_err_as_bug: bool, +) -> (clean::Crate, RenderInfo, Vec) { // Parse, resolve, and typecheck the given crate. let cpath = match input { @@ -388,7 +398,9 @@ pub fn run_core(search_paths: SearchPaths, }; driver::spawn_thread_pool(sessopts, move |sessopts| { let source_map = Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping())); - let diagnostic_handler = new_handler(error_format, Some(source_map.clone())); + let diagnostic_handler = new_handler(error_format, + Some(source_map.clone()), + treat_err_as_bug); let mut sess = session::build_session_( sessopts, cpath, diagnostic_handler, source_map, @@ -443,12 +455,10 @@ pub fn run_core(search_paths: SearchPaths, |_| Ok(())); let driver::InnerExpansionResult { mut hir_forest, - mut resolver, + resolver, .. } = abort_on_err(result, &sess); - resolver.ignore_extern_prelude_feature = true; - // We need to hold on to the complete resolver, so we clone everything // for the analysis passes to use. Suboptimal, but necessary in the // current architecture. @@ -506,16 +516,17 @@ pub fn run_core(search_paths: SearchPaths, clean::path_to_def(&tcx, &["core", "marker", "Send"]) }; + let mut renderinfo = RenderInfo::default(); + renderinfo.access_levels = access_levels; + let ctxt = DocContext { tcx, resolver: &resolver, crate_name, cstore: cstore.clone(), - populated_all_crate_impls: Cell::new(false), - access_levels: RefCell::new(access_levels), external_traits: Default::default(), active_extern_traits: Default::default(), - renderinfo: Default::default(), + renderinfo: RefCell::new(renderinfo), ty_substs: Default::default(), lt_substs: Default::default(), impl_trait_bounds: Default::default(), diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 6d96bc8e360..b8e27c53170 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mem; - use clean::*; pub struct StripItem(pub Item); @@ -116,11 +114,14 @@ fn fold_mod(&mut self, m: Module) -> Module { fn fold_crate(&mut self, mut c: Crate) -> Crate { c.module = c.module.take().and_then(|module| self.fold_item(module)); - let traits = mem::replace(&mut c.external_traits, Default::default()); - c.external_traits.extend(traits.into_iter().map(|(k, mut v)| { - v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); - (k, v) - })); + { + let guard = c.external_traits.lock(); + let traits = guard.replace(Default::default()); + guard.borrow_mut().extend(traits.into_iter().map(|(k, mut v)| { + v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); + (k, v) + })); + } c } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d4e22dd91d7..3e1720f8b8a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -313,7 +313,7 @@ pub struct Cache { // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing // the access levels from crateanalysis. - pub access_levels: Arc>, + pub access_levels: AccessLevels, /// The version of the crate being documented, if given from the `--crate-version` flag. pub crate_version: Option, @@ -337,6 +337,15 @@ pub struct Cache { // and their parent id here and indexes them at the end of crate parsing. orphan_impl_items: Vec<(DefId, clean::Item)>, + // Similarly to `orphan_impl_items`, sometimes trait impls are picked up + // even though the trait itself is not exported. This can happen if a trait + // was defined in function/expression scope, since the impl will be picked + // up by `collect-trait-impls` but the trait won't be scraped out in the HIR + // crawl. In order to prevent crashes when looking for spotlight traits or + // when gathering trait documentation on a type, hold impls here while + // folding and add them to the cache later on if we find the trait. + orphan_trait_impls: Vec<(DefId, FxHashSet, Impl)>, + /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. aliases: FxHashMap>, @@ -350,6 +359,7 @@ pub struct RenderInfo { pub external_paths: ::core::ExternalPaths, pub external_typarams: FxHashMap, pub exact_paths: FxHashMap>, + pub access_levels: AccessLevels, pub deref_trait_did: Option, pub deref_mut_trait_did: Option, pub owned_box_did: Option, @@ -569,6 +579,7 @@ pub fn run(mut krate: clean::Crate, external_paths, external_typarams, exact_paths, + access_levels, deref_trait_did, deref_mut_trait_did, owned_box_did, @@ -591,10 +602,11 @@ pub fn run(mut krate: clean::Crate, extern_locations: FxHashMap(), primitive_locations: FxHashMap(), stripped_mod: false, - access_levels: krate.access_levels.clone(), + access_levels, crate_version: krate.version.take(), orphan_impl_items: Vec::new(), - traits: mem::replace(&mut krate.external_traits, FxHashMap()), + orphan_trait_impls: Vec::new(), + traits: krate.external_traits.lock().replace(FxHashMap()), deref_trait_did, deref_mut_trait_did, owned_box_did, @@ -636,6 +648,14 @@ pub fn run(mut krate: clean::Crate, cache.stack.push(krate.name.clone()); krate = cache.fold_crate(krate); + for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { + if cache.traits.contains_key(&trait_did) { + for did in dids { + cache.impls.entry(did).or_insert(vec![]).push(impl_.clone()); + } + } + } + // Build our search index let index = build_index(&krate, &mut cache); @@ -1223,6 +1243,10 @@ fn emit_source(&mut self, filename: &FileName) -> io::Result<()> { impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option { + if item.def_id.is_local() { + debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); + } + // If this is a stripped module, // we don't want it or its children in the search index. let orig_stripped_mod = match item.inner { @@ -1453,10 +1477,16 @@ fn fold_item(&mut self, item: clean::Item) -> Option { } else { unreachable!() }; - for did in dids { - self.impls.entry(did).or_default().push(Impl { - impl_item: item.clone(), - }); + let impl_item = Impl { + impl_item: item, + }; + if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { + for did in dids { + self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + } + } else { + let trait_did = impl_item.trait_did().unwrap(); + self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None } else { @@ -1830,8 +1860,8 @@ fn render_item(&self, *slot.borrow_mut() = self.current.clone(); }); - let mut title = if it.is_primitive() { - // No need to include the namespace for primitive types + let mut title = if it.is_primitive() || it.is_keyword() { + // No need to include the namespace for primitive types and keywords String::new() } else { self.current.join("::") @@ -2301,17 +2331,21 @@ fn document_non_exhaustive(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::R } fn name_key(name: &str) -> (&str, u64, usize) { + let end = name.bytes() + .rposition(|b| b.is_ascii_digit()).map_or(name.len(), |i| i + 1); + // find number at end - let split = name.bytes().rposition(|b| b < b'0' || b'9' < b).map_or(0, |s| s + 1); + let split = name[0..end].bytes() + .rposition(|b| !b.is_ascii_digit()).map_or(0, |i| i + 1); // count leading zeroes let after_zeroes = - name[split..].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra); + name[split..end].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra); // sort leading zeroes last let num_zeroes = after_zeroes - split; - match name[split..].parse() { + match name[split..end].parse() { Ok(n) => (&name[..split], n, num_zeroes), Err(_) => (name, 0, num_zeroes), } @@ -2702,6 +2736,14 @@ fn bounds(t_bounds: &[clean::GenericBound]) -> String { bounds } +fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { + let lhs = format!("{}", lhs.inner_impl()); + let rhs = format!("{}", rhs.inner_impl()); + + // lhs and rhs are formatted as HTML, which may be unnecessary + name_key(&lhs).cmp(&name_key(&rhs)) +} + fn item_trait( w: &mut fmt::Formatter, cx: &Context, @@ -2905,9 +2947,12 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean:: .map_or(true, |d| cache.paths.contains_key(&d))); - let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter() + let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter() .partition(|i| i.inner_impl().synthetic); + synthetic.sort_by(compare_impl); + concrete.sort_by(compare_impl); + if !foreign.is_empty() { write!(w, "

@@ -4716,6 +4761,7 @@ fn test_name_sorting() { "Fruit1", "Fruit01", "Fruit2", "Fruit02", "Fruit20", + "Fruit30x", "Fruit100", "Pear"]; let mut sorted = names.to_owned(); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bc471d42704..5607c97a496 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -24,6 +24,7 @@ #![feature(ptr_offset_from)] #![feature(crate_visibility_modifier)] #![feature(const_fn)] +#![feature(drain_filter)] #![recursion_limit="256"] @@ -48,6 +49,7 @@ extern crate pulldown_cmark; extern crate tempfile; extern crate minifier; +extern crate parking_lot; extern crate serialize as rustc_serialize; // used by deriving @@ -404,8 +406,11 @@ fn main_args(args: &[String]) -> isize { `short` (instead was `{}`)", arg)); } }; + let treat_err_as_bug = matches.opt_strs("Z").iter().any(|x| { + *x == "treat-err-as-bug" + }); - let diag = core::new_handler(error_format, None); + let diag = core::new_handler(error_format, None, treat_err_as_bug); // check for deprecated options check_deprecated_options(&matches, &diag); @@ -560,7 +565,7 @@ fn main_args(args: &[String]) -> isize { let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, error_format, move |out| { let Output { krate, passes, renderinfo } = out; - let diag = core::new_handler(error_format, None); + let diag = core::new_handler(error_format, None, treat_err_as_bug); info!("going to format"); match output_format.as_ref().map(|s| &**s) { Some("html") | None => { @@ -609,16 +614,19 @@ fn acquire_input(input: PathBuf, /// Extracts `--extern CRATE=PATH` arguments from `matches` and /// returns a map mapping crate names to their paths or else an /// error message. +// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`. fn parse_externs(matches: &getopts::Matches) -> Result { let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); for arg in &matches.opt_strs("extern") { let mut parts = arg.splitn(2, '='); let name = parts.next().ok_or("--extern value must not be empty".to_string())?; - let location = parts.next() - .ok_or("--extern value must be of the format `foo=bar`" - .to_string())?; + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !nightly_options::is_unstable_enabled(matches) { + return Err("the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`".to_string()); + } let name = name.to_string(); - externs.entry(name).or_default().insert(location.to_string()); + externs.entry(name).or_default().insert(location); } Ok(Externs::new(externs)) } @@ -691,6 +699,9 @@ fn rust_input(cratefile: PathBuf, let force_unstable_if_unmarked = matches.opt_strs("Z").iter().any(|x| { *x == "force-unstable-if-unmarked" }); + let treat_err_as_bug = matches.opt_strs("Z").iter().any(|x| { + *x == "treat-err-as-bug" + }); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -703,7 +714,8 @@ fn rust_input(cratefile: PathBuf, core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot, display_warnings, crate_name.clone(), force_unstable_if_unmarked, edition, cg, error_format, - lint_opts, lint_cap, describe_lints, manual_passes, default_passes); + lint_opts, lint_cap, describe_lints, manual_passes, default_passes, + treat_err_as_bug); info!("finished with rustc"); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 2d5512c538f..7b2eb2259d6 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -69,16 +69,21 @@ fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { /// Resolve a given string as a path, along with whether or not it is /// in the value namespace. Also returns an optional URL fragment in the case /// of variants and methods - fn resolve(&self, path_str: &str, is_val: bool, current_item: &Option) + fn resolve(&self, + path_str: &str, + is_val: bool, + current_item: &Option, + parent_id: Option) -> Result<(Def, Option), ()> { let cx = self.cx; // In case we're in a module, try to resolve the relative // path - if let Some(id) = self.mod_ids.last() { + if let Some(id) = parent_id.or(self.mod_ids.last().cloned()) { + // FIXME: `with_scope` requires the NodeId of a module let result = cx.resolver.borrow_mut() - .with_scope(*id, + .with_scope(id, |resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, is_val) @@ -129,8 +134,9 @@ fn resolve(&self, path_str: &str, is_val: bool, current_item: &Option) } } + // FIXME: `with_scope` requires the NodeId of a module let ty = cx.resolver.borrow_mut() - .with_scope(*id, + .with_scope(id, |resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path, false) })?; @@ -218,6 +224,20 @@ fn fold_item(&mut self, mut item: Item) -> Option { None }; + // FIXME: get the resolver to work with non-local resolve scopes + let parent_node = self.cx.as_local_node_id(item.def_id).and_then(|node_id| { + // FIXME: this fails hard for impls in non-module scope, but is necessary for the + // current resolve() implementation + match self.cx.tcx.hir.get_module_parent_node(node_id) { + id if id != node_id => Some(id), + _ => None, + } + }); + + if parent_node.is_some() { + debug!("got parent node for {} {:?}, id {:?}", item.type_(), item.name, item.def_id); + } + let current_item = match item.inner { ModuleItem(..) => { if item.attrs.inner_docs { @@ -227,10 +247,10 @@ fn fold_item(&mut self, mut item: Item) -> Option { None } } else { - match self.mod_ids.last() { - Some(parent) if *parent != NodeId::new(0) => { + match parent_node.or(self.mod_ids.last().cloned()) { + Some(parent) if parent != NodeId::new(0) => { //FIXME: can we pull the parent module's name from elsewhere? - Some(self.cx.tcx.hir.name(*parent).to_string()) + Some(self.cx.tcx.hir.name(parent).to_string()) } _ => None, } @@ -294,7 +314,7 @@ fn fold_item(&mut self, mut item: Item) -> Option { match kind { PathKind::Value => { - if let Ok(def) = self.resolve(path_str, true, ¤t_item) { + if let Ok(def) = self.resolve(path_str, true, ¤t_item, parent_node) { def } else { resolution_failure(cx, &item.attrs, path_str, &dox, link_range); @@ -305,7 +325,7 @@ fn fold_item(&mut self, mut item: Item) -> Option { } } PathKind::Type => { - if let Ok(def) = self.resolve(path_str, false, ¤t_item) { + if let Ok(def) = self.resolve(path_str, false, ¤t_item, parent_node) { def } else { resolution_failure(cx, &item.attrs, path_str, &dox, link_range); @@ -316,16 +336,18 @@ fn fold_item(&mut self, mut item: Item) -> Option { PathKind::Unknown => { // try everything! if let Some(macro_def) = macro_resolve(cx, path_str) { - if let Ok(type_def) = self.resolve(path_str, false, ¤t_item) { + if let Ok(type_def) = + self.resolve(path_str, false, ¤t_item, parent_node) + { let (type_kind, article, type_disambig) = type_ns_kind(type_def.0, path_str); ambiguity_error(cx, &item.attrs, path_str, article, type_kind, &type_disambig, "a", "macro", &format!("macro@{}", path_str)); continue; - } else if let Ok(value_def) = self.resolve(path_str, - true, - ¤t_item) { + } else if let Ok(value_def) = + self.resolve(path_str, true, ¤t_item, parent_node) + { let (value_kind, value_disambig) = value_ns_kind(value_def.0, path_str) .expect("struct and mod cases should have been \ @@ -335,12 +357,16 @@ fn fold_item(&mut self, mut item: Item) -> Option { "a", "macro", &format!("macro@{}", path_str)); } (macro_def, None) - } else if let Ok(type_def) = self.resolve(path_str, false, ¤t_item) { + } else if let Ok(type_def) = + self.resolve(path_str, false, ¤t_item, parent_node) + { // It is imperative we search for not-a-value first // Otherwise we will find struct ctors for when we are looking // for structs, and the link won't work. // if there is something in both namespaces - if let Ok(value_def) = self.resolve(path_str, true, ¤t_item) { + if let Ok(value_def) = + self.resolve(path_str, true, ¤t_item, parent_node) + { let kind = value_ns_kind(value_def.0, path_str); if let Some((value_kind, value_disambig)) = kind { let (type_kind, article, type_disambig) @@ -352,7 +378,9 @@ fn fold_item(&mut self, mut item: Item) -> Option { } } type_def - } else if let Ok(value_def) = self.resolve(path_str, true, ¤t_item) { + } else if let Ok(value_def) = + self.resolve(path_str, true, ¤t_item, parent_node) + { value_def } else { resolution_failure(cx, &item.attrs, path_str, &dox, link_range); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs new file mode 100644 index 00000000000..70e1a9b0ebc --- /dev/null +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -0,0 +1,219 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use clean::*; + +use rustc::util::nodemap::FxHashSet; +use rustc::hir::def_id::DefId; + +use super::Pass; +use core::DocContext; +use fold::DocFolder; + +pub const COLLECT_TRAIT_IMPLS: Pass = + Pass::early("collect-trait-impls", collect_trait_impls, + "retrieves trait impls for items in the crate"); + +pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate { + let mut synth = SyntheticImplCollector::new(cx); + let mut krate = synth.fold_crate(krate); + + let prims: FxHashSet = + krate.primitives.iter().map(|p| p.1).collect(); + + let crate_items = { + let mut coll = ItemCollector::new(); + krate = coll.fold_crate(krate); + coll.items + }; + + let mut new_items = Vec::new(); + + for &cnum in cx.tcx.crates().iter() { + for &did in cx.tcx.all_trait_implementations(cnum).iter() { + inline::build_impl(cx, did, &mut new_items); + } + } + + // Also try to inline primitive impls from other crates. + let lang_items = cx.tcx.lang_items(); + let primitive_impls = [ + lang_items.isize_impl(), + lang_items.i8_impl(), + lang_items.i16_impl(), + lang_items.i32_impl(), + lang_items.i64_impl(), + lang_items.i128_impl(), + lang_items.usize_impl(), + lang_items.u8_impl(), + lang_items.u16_impl(), + lang_items.u32_impl(), + lang_items.u64_impl(), + lang_items.u128_impl(), + lang_items.f32_impl(), + lang_items.f64_impl(), + lang_items.f32_runtime_impl(), + lang_items.f64_runtime_impl(), + lang_items.char_impl(), + lang_items.str_impl(), + lang_items.slice_impl(), + lang_items.slice_u8_impl(), + lang_items.str_alloc_impl(), + lang_items.slice_alloc_impl(), + lang_items.slice_u8_alloc_impl(), + lang_items.const_ptr_impl(), + lang_items.mut_ptr_impl(), + ]; + + for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { + if !def_id.is_local() { + inline::build_impl(cx, def_id, &mut new_items); + + let auto_impls = get_auto_traits_with_def_id(cx, def_id); + let blanket_impls = get_blanket_impls_with_def_id(cx, def_id); + let mut renderinfo = cx.renderinfo.borrow_mut(); + + let new_impls: Vec = auto_impls.into_iter() + .chain(blanket_impls.into_iter()) + .filter(|i| renderinfo.inlined.insert(i.def_id)) + .collect(); + + new_items.extend(new_impls); + } + } + + let mut cleaner = BadImplStripper { + prims, + items: crate_items, + }; + + // scan through included items ahead of time to splice in Deref targets to the "valid" sets + for it in &new_items { + if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = it.inner { + if cleaner.keep_item(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() { + let target = items.iter().filter_map(|item| { + match item.inner { + TypedefItem(ref t, true) => Some(&t.type_), + _ => None, + } + }).next().expect("Deref impl without Target type"); + + if let Some(prim) = target.primitive_type() { + cleaner.prims.insert(prim); + } else if let Some(did) = target.def_id() { + cleaner.items.insert(did); + } + } + } + } + + new_items.retain(|it| { + if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = it.inner { + cleaner.keep_item(for_) || + trait_.as_ref().map_or(false, |t| cleaner.keep_item(t)) || + blanket_impl.is_some() + } else { + true + } + }); + + // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations` + // doesn't work with it anyway, so pull them from the HIR map instead + for &trait_did in cx.all_traits.iter() { + for &impl_node in cx.tcx.hir.trait_impls(trait_did) { + let impl_did = cx.tcx.hir.local_def_id(impl_node); + inline::build_impl(cx, impl_did, &mut new_items); + } + } + + if let Some(ref mut it) = krate.module { + if let ModuleItem(Module { ref mut items, .. }) = it.inner { + items.extend(synth.impls); + items.extend(new_items); + } else { + panic!("collect-trait-impls can't run"); + } + } else { + panic!("collect-trait-impls can't run"); + } + + krate +} + +struct SyntheticImplCollector<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>, + impls: Vec, +} + +impl<'a, 'tcx, 'rcx, 'cstore> SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> { + fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { + SyntheticImplCollector { + cx, + impls: Vec::new(), + } + } +} + +impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> { + fn fold_item(&mut self, i: Item) -> Option { + if i.is_struct() || i.is_enum() || i.is_union() { + if let (Some(node_id), Some(name)) = + (self.cx.tcx.hir.as_local_node_id(i.def_id), i.name.clone()) + { + self.impls.extend(get_auto_traits_with_node_id(self.cx, node_id, name.clone())); + self.impls.extend(get_blanket_impls_with_node_id(self.cx, node_id, name)); + } else { + self.impls.extend(get_auto_traits_with_def_id(self.cx, i.def_id)); + self.impls.extend(get_blanket_impls_with_def_id(self.cx, i.def_id)); + } + } + + self.fold_item_recur(i) + } +} + +#[derive(Default)] +struct ItemCollector { + items: FxHashSet, +} + +impl ItemCollector { + fn new() -> Self { + Self::default() + } +} + +impl DocFolder for ItemCollector { + fn fold_item(&mut self, i: Item) -> Option { + self.items.insert(i.def_id); + + self.fold_item_recur(i) + } +} + +struct BadImplStripper { + prims: FxHashSet, + items: FxHashSet, +} + +impl BadImplStripper { + fn keep_item(&self, ty: &Type) -> bool { + if let Generic(_) = ty { + // keep impls made on generics + true + } else if let Some(prim) = ty.primitive_type() { + self.prims.contains(&prim) + } else if let Some(did) = ty.def_id() { + self.items.contains(&did) + } else { + false + } + } +} diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 16251877bb1..24fec62dd57 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -43,6 +43,9 @@ mod collect_intra_doc_links; pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; +mod collect_trait_impls; +pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS; + /// Represents a single pass. #[derive(Copy, Clone)] pub enum Pass { @@ -132,10 +135,12 @@ pub fn late_fn(self) -> Option clean::Crate> { STRIP_PRIV_IMPORTS, PROPAGATE_DOC_CFG, COLLECT_INTRA_DOC_LINKS, + COLLECT_TRAIT_IMPLS, ]; /// The list of passes run by default. pub const DEFAULT_PASSES: &'static [&'static str] = &[ + "collect-trait-impls", "strip-hidden", "strip-private", "collect-intra-doc-links", @@ -146,6 +151,7 @@ pub fn late_fn(self) -> Option clean::Crate> { /// The list of default passes run with `--document-private-items` is passed to rustdoc. pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[ + "collect-trait-impls", "strip-priv-imports", "collect-intra-doc-links", "collapse-docs", @@ -189,6 +195,7 @@ fn fold_item(&mut self, i: Item) -> Option { // We need to recurse into stripped modules to strip things // like impl methods but when doing so we must not add any // items to the `retained` set. + debug!("Stripper: recursing into stripped {} {:?}", i.type_(), i.name); let old = mem::replace(&mut self.update_retained, false); let ret = self.fold_item_recur(i); self.update_retained = old; @@ -212,6 +219,7 @@ fn fold_item(&mut self, i: Item) -> Option { | clean::ForeignTypeItem => { if i.def_id.is_local() { if !self.access_levels.is_exported(i.def_id) { + debug!("Stripper: stripping {} {:?}", i.type_(), i.name); return None; } } @@ -225,6 +233,7 @@ fn fold_item(&mut self, i: Item) -> Option { clean::ModuleItem(..) => { if i.def_id.is_local() && i.visibility != Some(clean::Public) { + debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); let ret = StripItem(self.fold_item_recur(i).unwrap()).strip(); self.update_retained = old; @@ -296,11 +305,13 @@ fn fold_item(&mut self, i: Item) -> Option { } if let Some(did) = imp.for_.def_id() { if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) { + debug!("ImplStripper: impl item for stripped type; removing"); return None; } } if let Some(did) = imp.trait_.def_id() { if did.is_local() && !self.retained.contains(&did) { + debug!("ImplStripper: impl item for stripped trait; removing"); return None; } } @@ -308,6 +319,8 @@ fn fold_item(&mut self, i: Item) -> Option { for typaram in generics { if let Some(did) = typaram.def_id() { if did.is_local() && !self.retained.contains(&did) { + debug!("ImplStripper: stripped item in trait's generics; \ + removing impl"); return None; } } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index cc0b6fb6d67..24dd4cc13bf 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -35,7 +35,9 @@ pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate { // strip all impls referencing stripped items let mut stripper = ImplStripper { retained: &retained }; - stripper.fold_crate(krate) + let krate = stripper.fold_crate(krate); + + krate } struct Stripper<'a> { @@ -46,7 +48,7 @@ struct Stripper<'a> { impl<'a> fold::DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if i.attrs.lists("doc").has_word("hidden") { - debug!("found one in strip_hidden; removing"); + debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name); // use a dedicated hidden item for given item type if any match i.inner { clean::StructFieldItem(..) | clean::ModuleItem(..) => { diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 3b17a768ffd..46d0034497e 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -22,10 +22,10 @@ /// Strip private items from the point of view of a crate or externally from a /// crate, specified by the `xcrate` flag. -pub fn strip_private(mut krate: clean::Crate, _: &DocContext) -> clean::Crate { +pub fn strip_private(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate { // This stripper collects all *retained* nodes. let mut retained = DefIdSet(); - let access_levels = krate.access_levels.clone(); + let access_levels = cx.renderinfo.borrow().access_levels.clone(); // strip all private items { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3b07a2ccdde..8a9ca924ee1 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -775,7 +775,7 @@ fn main() { assert_eq!(2+2, 4); }".to_string(); let output = make_test(input, None, false, &opts); - assert_eq!(output, (expected.clone(), 2)); + assert_eq!(output, (expected, 2)); } #[test] @@ -973,7 +973,7 @@ fn main() { assert_eq!(2+2, 4); }".to_string(); let output = make_test(input, None, false, &opts); - assert_eq!(output, (expected.clone(), 2)); + assert_eq!(output, (expected, 2)); } #[test] @@ -988,7 +988,7 @@ fn make_test_dont_insert_main() { //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);".to_string(); let output = make_test(input, None, true, &opts); - assert_eq!(output, (expected.clone(), 1)); + assert_eq!(output, (expected, 1)); } #[test] @@ -1003,6 +1003,6 @@ fn make_test_display_warnings() { assert_eq!(2+2, 4); }".to_string(); let output = make_test(input, None, false, &opts); - assert_eq!(output, (expected.clone(), 1)); + assert_eq!(output, (expected, 1)); } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 0aaf2d526f9..0e12fd34eb7 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -269,7 +269,10 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool { Def::Enum(did) | Def::ForeignTy(did) | Def::TyAlias(did) if !self_is_hidden => { - self.cx.access_levels.borrow_mut().map.insert(did, AccessLevel::Public); + self.cx.renderinfo + .borrow_mut() + .access_levels.map + .insert(did, AccessLevel::Public); }, Def::Mod(did) => if !self_is_hidden { ::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did); @@ -284,7 +287,7 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool { Some(n) => n, None => return false }; - let is_private = !self.cx.access_levels.borrow().is_public(def_did); + let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(def_did); let is_hidden = inherits_doc_hidden(self.cx, def_node_id); // Only inline if requested or if the item would otherwise be stripped @@ -510,9 +513,9 @@ pub fn visit_item(&mut self, item: &hir::Item, ref tr, ref ty, ref item_ids) => { - // Don't duplicate impls when inlining, we'll pick them up - // regardless of where they're located. - if !self.inlining { + // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick + // them up regardless of where they're located. + if !self.inlining && tr.is_none() { let items = item_ids.iter() .map(|ii| self.cx.tcx.hir.impl_item(ii.id).clone()) .collect(); diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 10a4e69dcc6..fd81f937f30 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -38,7 +38,7 @@ pub fn new( ) -> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> { LibEmbargoVisitor { cx, - access_levels: cx.access_levels.borrow_mut(), + access_levels: RefMut::map(cx.renderinfo.borrow_mut(), |ri| &mut ri.access_levels), prev_level: Some(AccessLevel::Public), visited_mods: FxHashSet() } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 768357ec8dc..547f97cc8ac 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -742,7 +742,9 @@ fn new_internal( ) -> Result, CollectionAllocErr> { unsafe { let ret = RawTable::new_uninitialized_internal(capacity, fallibility)?; - ptr::write_bytes(ret.hashes.ptr(), 0, capacity); + if capacity > 0 { + ptr::write_bytes(ret.hashes.ptr(), 0, capacity); + } Ok(ret) } } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index a37a5e8ae82..a3345df5e0d 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -171,5 +171,8 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use self::os_str::{OsString, OsStr}; +#[stable(feature = "raw_os", since = "1.1.0")] +pub use core::ffi::c_void; + mod c_str; mod os_str; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 237af2f04e5..e9390630445 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -34,7 +34,9 @@ /// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust /// and platform-native string values, and in particular allowing a Rust string -/// to be converted into an "OS" string with no cost if possible. +/// to be converted into an "OS" string with no cost if possible. A consequence +/// of this is that `OsString` instances are *not* `NUL` terminated; in order +/// to pass to e.g. Unix system call, you should create a [`CStr`]. /// /// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former /// in each pair are owned strings; the latter are borrowed @@ -65,6 +67,7 @@ /// /// [`OsStr`]: struct.OsStr.html /// [`&OsStr`]: struct.OsStr.html +/// [`CStr`]: struct.CStr.html /// [`From`]: ../convert/trait.From.html /// [`String`]: ../string/struct.String.html /// [`&str`]: ../primitive.str.html diff --git a/src/libstd/future.rs b/src/libstd/future.rs index d9657f691c7..262646738cf 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -12,7 +12,7 @@ use core::cell::Cell; use core::marker::Unpin; -use core::pin::PinMut; +use core::pin::Pin; use core::option::Option; use core::ptr::NonNull; use core::task::{self, Poll}; @@ -42,8 +42,8 @@ impl> !Unpin for GenFuture {} #[unstable(feature = "gen_future", issue = "50547")] impl> Future for GenFuture { type Output = T::Return; - fn poll(self: PinMut, cx: &mut task::Context) -> Poll { - set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } { + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + set_task_cx(cx, || match unsafe { Pin::get_mut_unchecked(self).0.resume() } { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), }) @@ -108,9 +108,9 @@ pub fn get_task_cx(f: F) -> R #[unstable(feature = "gen_future", issue = "50547")] /// Polls a future in the current thread-local task context. -pub fn poll_in_task_cx(f: PinMut) -> Poll +pub fn poll_in_task_cx(f: Pin<&mut F>) -> Poll where F: Future { - get_task_cx(|cx| f.poll(cx)) + get_task_cx(|cx| F::poll(f, cx)) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 17f6923eae7..1eb76d6c45e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -435,7 +435,7 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::format; #[unstable(feature = "pin", issue = "49150")] -pub use alloc_crate::pin; +pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::slice; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index b649ec2340e..e60ef46e738 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -230,7 +230,7 @@ macro_rules! await { loop { if let $crate::task::Poll::Ready(x) = $crate::future::poll_in_task_cx(unsafe { - $crate::pin::PinMut::new_unchecked(&mut pinned) + $crate::pin::Pin::new_unchecked(&mut pinned) }) { break x; diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index e80c3eeb876..ff35325ab4f 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -554,6 +554,7 @@ fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { #[stable(feature = "ip_from_ip", since = "1.16.0")] impl From for SocketAddr { + /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. fn from(sock4: SocketAddrV4) -> SocketAddr { SocketAddr::V4(sock4) } @@ -561,6 +562,7 @@ fn from(sock4: SocketAddrV4) -> SocketAddr { #[stable(feature = "ip_from_ip", since = "1.16.0")] impl From for SocketAddr { + /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. fn from(sock6: SocketAddrV6) -> SocketAddr { SocketAddr::V6(sock6) } @@ -568,6 +570,12 @@ fn from(sock6: SocketAddrV6) -> SocketAddr { #[stable(feature = "addr_from_into_ip", since = "1.17.0")] impl> From<(I, u16)> for SocketAddr { + /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. + /// + /// This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`] + /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`]. + /// + /// `u16` is treated as port of the newly created [`SocketAddr`]. fn from(pieces: (I, u16)) -> SocketAddr { SocketAddr::new(pieces.0.into(), pieces.1) } diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs index dc33747c05b..95faf3a5dd6 100644 --- a/src/libstd/os/raw/mod.rs +++ b/src/libstd/os/raw/mod.rs @@ -18,8 +18,6 @@ #![stable(feature = "raw_os", since = "1.1.0")] -use fmt; - #[doc(include = "os/raw/char.md")] #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", @@ -83,40 +81,9 @@ #[doc(include = "os/raw/double.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; -/// Equivalent to C's `void` type when used as a [pointer]. -/// -/// In essence, `*const c_void` is equivalent to C's `const void*` -/// and `*mut c_void` is equivalent to C's `void*`. That said, this is -/// *not* the same as C's `void` return type, which is Rust's `()` type. -/// -/// Ideally, this type would be equivalent to [`!`], but currently it may -/// be more ideal to use `c_void` for FFI purposes. -/// -/// [`!`]: ../../primitive.never.html -/// [pointer]: ../../primitive.pointer.html -// NB: For LLVM to recognize the void pointer type and by extension -// functions like malloc(), we need to have it represented as i8* in -// LLVM bitcode. The enum used here ensures this and prevents misuse -// of the "raw" type by only having private variants.. We need two -// variants, because the compiler complains about the repr attribute -// otherwise. -#[repr(u8)] #[stable(feature = "raw_os", since = "1.1.0")] -pub enum c_void { - #[unstable(feature = "c_void_variant", reason = "should not have to exist", - issue = "0")] - #[doc(hidden)] __variant1, - #[unstable(feature = "c_void_variant", reason = "should not have to exist", - issue = "0")] - #[doc(hidden)] __variant2, -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for c_void { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("c_void") - } -} +#[doc(no_inline)] +pub use core::ffi::c_void; #[cfg(test)] #[allow(unused_imports)] diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 47547aedcbd..bd7a92e9b3f 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -16,7 +16,7 @@ use cell::UnsafeCell; use fmt; use future::Future; -use pin::PinMut; +use pin::Pin; use ops::{Deref, DerefMut}; use panicking; use ptr::{Unique, NonNull}; @@ -327,9 +327,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { impl<'a, F: Future> Future for AssertUnwindSafe { type Output = F::Output; - fn poll(self: PinMut, cx: &mut task::Context) -> Poll { - let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) }; - pinned_field.poll(cx) + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }; + F::poll(pinned_field, cx) } } diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/wasm/cmath.rs index 87ac2091cad..64fc14d42d9 100644 --- a/src/libstd/sys/wasm/cmath.rs +++ b/src/libstd/sys/wasm/cmath.rs @@ -74,46 +74,19 @@ pub unsafe fn tanhf(n: f32) -> f32 { f64::tanh(n as f64) as f32 } -// Right now all these functions, the f64 version of the functions above, all -// shell out to random names. These names aren't actually defined anywhere, per -// se, but we need this to compile somehow. -// -// The idea with this is that when you're using wasm then, for now, we have no -// way of providing an implementation of these which delegates to a "correct" -// implementation. For example most wasm applications probably just want to -// delegate to the javascript `Math` object and its related functions, but wasm -// doesn't currently have the ability to seamlessly do that (when you -// instantiate a module you have to set that up). -// -// As a result these are just defined here with "hopefully helpful" names. The -// symbols won't ever be needed or show up unless these functions are called, -// and hopefully when they're called the errors are self-explanatory enough to -// figure out what's going on. - +// These symbols are all defined in `compiler-builtins` extern { - #[link_name = "Math_acos"] pub fn acos(n: f64) -> f64; - #[link_name = "Math_asin"] pub fn asin(n: f64) -> f64; - #[link_name = "Math_atan"] pub fn atan(n: f64) -> f64; - #[link_name = "Math_atan2"] pub fn atan2(a: f64, b: f64) -> f64; - #[link_name = "Math_cbrt"] pub fn cbrt(n: f64) -> f64; - #[link_name = "Math_cosh"] pub fn cosh(n: f64) -> f64; - #[link_name = "Math_expm1"] pub fn expm1(n: f64) -> f64; pub fn fdim(a: f64, b: f64) -> f64; - #[link_name = "Math_log1p"] pub fn log1p(n: f64) -> f64; - #[link_name = "Math_sinh"] pub fn sinh(n: f64) -> f64; - #[link_name = "Math_tan"] pub fn tan(n: f64) -> f64; - #[link_name = "Math_tanh"] pub fn tanh(n: f64) -> f64; - #[link_name = "Math_hypot"] pub fn hypot(x: f64, y: f64) -> f64; } diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index b841afe1a51..d09a233ed89 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -622,7 +622,8 @@ fn no_lookup_host_duplicates() { Ok(lh) => lh, Err(e) => panic!("couldn't resolve `localhost': {}", e) }; - let _na = lh.map(|sa| *addrs.entry(sa).or_insert(0) += 1).count(); - assert!(addrs.values().filter(|&&v| v > 1).count() == 0); + for sa in lh { *addrs.entry(sa).or_insert(0) += 1; }; + assert_eq!(addrs.iter().filter(|&(_, &v)| v > 1).collect::>(), vec![], + "There should be no duplicate localhost entries"); } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index a7c7dbb1b40..3987ae83866 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -800,7 +800,14 @@ pub fn park() { match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { Ok(_) => {} Err(NOTIFIED) => { - thread.inner.state.store(EMPTY, SeqCst); + // We must read here, even though we know it will be `NOTIFIED`. + // This is because `unpark` may have been called again since we read + // `NOTIFIED` in the `compare_exchange` above. We must perform an + // acquire operation that synchronizes with that `unpark` to observe + // any writes it made before the call to unpark. To do that we must + // read from the write it made to `state`. + let old = thread.inner.state.swap(EMPTY, SeqCst); + assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); return; } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => panic!("inconsistent park state"), @@ -889,7 +896,9 @@ pub fn park_timeout(dur: Duration) { match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { Ok(_) => {} Err(NOTIFIED) => { - thread.inner.state.store(EMPTY, SeqCst); + // We must read again here, see `park`. + let old = thread.inner.state.swap(EMPTY, SeqCst); + assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); return; } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => panic!("inconsistent park_timeout state"), @@ -1058,23 +1067,22 @@ pub(crate) fn new(name: Option) -> Thread { /// [park]: fn.park.html #[stable(feature = "rust1", since = "1.0.0")] pub fn unpark(&self) { - loop { - match self.inner.state.compare_exchange(EMPTY, NOTIFIED, SeqCst, SeqCst) { - Ok(_) => return, // no one was waiting - Err(NOTIFIED) => return, // already unparked - Err(PARKED) => {} // gotta go wake someone up - _ => panic!("inconsistent state in unpark"), - } - - // Coordinate wakeup through the mutex and a condvar notification - let _lock = self.inner.lock.lock().unwrap(); - match self.inner.state.compare_exchange(PARKED, NOTIFIED, SeqCst, SeqCst) { - Ok(_) => return self.inner.cvar.notify_one(), - Err(NOTIFIED) => return, // a different thread unparked - Err(EMPTY) => {} // parked thread went away, try again - _ => panic!("inconsistent state in unpark"), - } + // To ensure the unparked thread will observe any writes we made + // before this call, we must perform a release operation that `park` + // can synchronize with. To do that we must write `NOTIFIED` even if + // `state` is already `NOTIFIED`. That is why this must be a swap + // rather than a compare-and-swap that returns if it reads `NOTIFIED` + // on failure. + match self.inner.state.swap(NOTIFIED, SeqCst) { + EMPTY => return, // no one was waiting + NOTIFIED => return, // already unparked + PARKED => {} // gotta go wake someone up + _ => panic!("inconsistent state in unpark"), } + + // Coordinate wakeup through the mutex and a condvar notification + let _lock = self.inner.lock.lock().unwrap(); + self.inner.cvar.notify_one() } /// Gets the thread's unique identifier. diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 63b70b12248..5d978b6b9e6 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -16,6 +16,7 @@ use edition::Edition; use parse::{token, ParseSess}; use OneVector; +use errors::Applicability; use ptr::P; @@ -123,7 +124,12 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { let error = |span, msg, suggestion: &str| { let mut err = self.sess.span_diagnostic.struct_span_err(span, msg); if !suggestion.is_empty() { - err.span_suggestion(span, "expected syntax is", suggestion.into()); + err.span_suggestion_with_applicability( + span, + "expected syntax is", + suggestion.into(), + Applicability::MaybeIncorrect, + ); } err.emit(); true diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 40903e8ad6c..33d0e76ca48 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -216,6 +216,14 @@ pub struct Invocation { pub expansion_data: ExpansionData, } +// Needed for feature-gating attributes used after derives or together with test/bench +#[derive(Clone, Copy, PartialEq)] +pub enum TogetherWith { + None, + Derive, + TestBench, +} + pub enum InvocationKind { Bang { mac: ast::Mac, @@ -226,6 +234,7 @@ pub enum InvocationKind { attr: Option, traits: Vec, item: Annotatable, + together_with: TogetherWith, }, Derive { path: Path, @@ -353,7 +362,7 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap(); let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy); self.collect_invocations(fragment, &[]) - } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { + } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind { if !item.derive_allowed() { let attr = attr::find_by_name(item.attrs(), "derive") .expect("`derive` attribute should exist"); @@ -1069,14 +1078,23 @@ fn collect_attr(&mut self, attr: Option, traits: Vec, item: Annotatable, - kind: AstFragmentKind) + kind: AstFragmentKind, + together_with: TogetherWith) -> AstFragment { - self.collect(kind, InvocationKind::Attr { attr, traits, item }) + self.collect(kind, InvocationKind::Attr { attr, traits, item, together_with }) } - fn find_attr_invoc(&self, attrs: &mut Vec) -> Option { + fn find_attr_invoc(&self, attrs: &mut Vec, together_with: &mut TogetherWith) + -> Option { let attr = attrs.iter() - .position(|a| !attr::is_known(a) && !is_builtin_attr(a)) + .position(|a| { + if a.path == "derive" { + *together_with = TogetherWith::Derive + } else if a.path == "rustc_test_marker2" { + *together_with = TogetherWith::TestBench + } + !attr::is_known(a) && !is_builtin_attr(a) + }) .map(|i| attrs.remove(i)); if let Some(attr) = &attr { if !self.cx.ecfg.enable_custom_inner_attributes() && @@ -1086,14 +1104,19 @@ fn find_attr_invoc(&self, attrs: &mut Vec) -> Option(&mut self, mut item: T) -> (Option, Vec, T) + fn classify_item(&mut self, mut item: T) + -> (Option, Vec, T, TogetherWith) where T: HasAttrs, { - let (mut attr, mut traits) = (None, Vec::new()); + let (mut attr, mut traits, mut together_with) = (None, Vec::new(), TogetherWith::None); item = item.map_attrs(|mut attrs| { if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, @@ -1102,19 +1125,20 @@ fn classify_item(&mut self, mut item: T) -> (Option, Vec(&mut self, mut item: T) -> (Option, T) { - let mut attr = None; + fn classify_nonitem(&mut self, mut item: T) + -> (Option, T, TogetherWith) { + let (mut attr, mut together_with) = (None, TogetherWith::None); item = item.map_attrs(|mut attrs| { if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, @@ -1123,11 +1147,11 @@ fn classify_nonitem(&mut self, mut item: T) -> (Option(&mut self, node: T) -> Option { @@ -1166,7 +1190,7 @@ fn fold_expr(&mut self, expr: P) -> P { expr.node = self.cfg.configure_expr_kind(expr.node); // ignore derives so they remain unused - let (attr, expr) = self.classify_nonitem(expr); + let (attr, expr, together_with) = self.classify_nonitem(expr); if attr.is_some() { // collect the invoc regardless of whether or not attributes are permitted here @@ -1175,7 +1199,7 @@ fn fold_expr(&mut self, expr: P) -> P { // AstFragmentKind::Expr requires the macro to emit an expression return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::Expr).make_expr(); + AstFragmentKind::Expr, together_with).make_expr(); } if let ast::ExprKind::Mac(mac) = expr.node { @@ -1191,14 +1215,13 @@ fn fold_opt_expr(&mut self, expr: P) -> Option> { expr.node = self.cfg.configure_expr_kind(expr.node); // ignore derives so they remain unused - let (attr, expr) = self.classify_nonitem(expr); + let (attr, expr, together_with) = self.classify_nonitem(expr); if attr.is_some() { attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr) - .make_opt_expr(); + AstFragmentKind::OptExpr, together_with).make_opt_expr(); } if let ast::ExprKind::Mac(mac) = expr.node { @@ -1230,19 +1253,18 @@ fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector { // we'll expand attributes on expressions separately if !stmt.is_expr() { - let (attr, derives, stmt_) = if stmt.is_item() { + let (attr, derives, stmt_, together_with) = if stmt.is_item() { self.classify_item(stmt) } else { // ignore derives on non-item statements so it falls through // to the unused-attributes lint - let (attr, stmt) = self.classify_nonitem(stmt); - (attr, vec![], stmt) + let (attr, stmt, together_with) = self.classify_nonitem(stmt); + (attr, vec![], stmt, together_with) }; if attr.is_some() || !derives.is_empty() { - return self.collect_attr(attr, derives, - Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts) - .make_stmts(); + return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt_)), + AstFragmentKind::Stmts, together_with).make_stmts(); } stmt = stmt_; @@ -1284,10 +1306,10 @@ fn fold_block(&mut self, block: P) -> P { fn fold_item(&mut self, item: P) -> OneVector> { let item = configure!(self, item); - let (attr, traits, item) = self.classify_item(item); + let (attr, traits, item, together_with) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::Item(item); - return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items(); + return self.collect_attr(attr, traits, Annotatable::Item(item), + AstFragmentKind::Items, together_with).make_items(); } match item.node { @@ -1359,11 +1381,10 @@ fn fold_item(&mut self, item: P) -> OneVector> { fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector { let item = configure!(self, item); - let (attr, traits, item) = self.classify_item(item); + let (attr, traits, item, together_with) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::TraitItem(P(item)); - return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems) - .make_trait_items() + return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)), + AstFragmentKind::TraitItems, together_with).make_trait_items() } match item.node { @@ -1379,11 +1400,10 @@ fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector { let item = configure!(self, item); - let (attr, traits, item) = self.classify_item(item); + let (attr, traits, item, together_with) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::ImplItem(P(item)); - return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems) - .make_impl_items(); + return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)), + AstFragmentKind::ImplItems, together_with).make_impl_items(); } match item.node { @@ -1414,12 +1434,12 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem) -> OneVector { - let (attr, traits, foreign_item) = self.classify_item(foreign_item); + let (attr, traits, foreign_item, together_with) = self.classify_item(foreign_item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::ForeignItem(P(foreign_item)); - return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems) - .make_foreign_items(); + return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)), + AstFragmentKind::ForeignItems, together_with) + .make_foreign_items(); } if let ast::ForeignItemKind::Macro(mac) = foreign_item.node { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 86247745c41..214bc9cffc4 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -32,6 +32,7 @@ use std::collections::hash_map::Entry; use rustc_data_structures::sync::Lrc; +use errors::Applicability; pub struct ParserAnyMacro<'a> { parser: Parser<'a>, @@ -187,10 +188,11 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, if comma_span == DUMMY_SP { err.note("you might be missing a comma"); } else { - err.span_suggestion_short( + err.span_suggestion_short_with_applicability( comma_span, "missing comma here", ", ".to_string(), + Applicability::MachineApplicable, ); } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7266d807d3b..d44d2146d82 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -394,18 +394,12 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows trait methods with arbitrary self types (active, arbitrary_self_types, "1.23.0", Some(44874), None), - // `crate` in paths - (active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)), - // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) (active, in_band_lifetimes, "1.23.0", Some(44524), None), // Generic associated types (RFC 1598) (active, generic_associated_types, "1.23.0", Some(44265), None), - // Resolve absolute paths as paths from other crates - (active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)), - // `extern` in paths (active, extern_in_paths, "1.23.0", Some(44660), None), @@ -455,9 +449,6 @@ pub fn walk_feature_fields(&self, mut f: F) // #[doc(alias = "...")] (active, doc_alias, "1.27.0", Some(50146), None), - // Access to crate names passed via `--extern` through prelude - (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)), - // Scoped lints (active, tool_lints, "1.28.0", Some(44690), None), @@ -515,6 +506,12 @@ pub fn walk_feature_fields(&self, mut f: F) // Self struct constructor (RFC 2302) (active, self_struct_ctor, "1.31.0", Some(51994), None), + + // allow mixing of bind-by-move in patterns and references to + // those identifiers in guards, *if* we are using MIR-borrowck + // (aka NLL). Essentially this means you need to be on + // edition:2018 or later. + (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), ); declare_features! ( @@ -677,7 +674,12 @@ pub fn walk_feature_fields(&self, mut f: F) (accepted, panic_handler, "1.30.0", Some(44489), None), // Used to preserve symbols (see llvm.used) (accepted, used, "1.30.0", Some(40289), None), - + // `crate` in paths + (accepted, crate_in_paths, "1.30.0", Some(45477), None), + // Resolve absolute paths as paths from other crates + (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), + // Access to crate names passed via `--extern` through prelude + (accepted, extern_prelude, "1.30.0", Some(44660), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -711,7 +713,7 @@ pub enum AttributeGate { impl AttributeGate { fn is_deprecated(&self) -> bool { match *self { - Gated(Stability::Deprecated(_), ..) => true, + Gated(Stability::Deprecated(_, _), ..) => true, _ => false, } } @@ -720,8 +722,9 @@ fn is_deprecated(&self) -> bool { #[derive(Copy, Clone, Debug)] pub enum Stability { Unstable, - // Argument is tracking issue link. - Deprecated(&'static str), + // First argument is tracking issue link; second argument is an optional + // help message, which defaults to "remove this attribute" + Deprecated(&'static str, Option<&'static str>), } // fn() is not Debug @@ -970,6 +973,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { "the `#[rustc_test_marker]` attribute \ is used internally to track tests", cfg_fn!(rustc_attrs))), + ("rustc_test_marker2", Normal, Gated(Stability::Unstable, + "rustc_attrs", + "temporarily used by rustc to report some errors", + cfg_fn!(rustc_attrs))), ("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "used internally for testing macro hygiene", @@ -1044,7 +1051,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { ("no_builtins", Whitelisted, Ungated), ("no_mangle", Whitelisted, Ungated), ("no_debug", Whitelisted, Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"), + Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), "no_debug", "the `#[no_debug]` attribute was an experimental feature that has been \ deprecated due to lack of demand", @@ -1057,7 +1064,8 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { cfg_fn!(omit_gdb_pretty_printer_section))), ("unsafe_destructor_blind_to_params", Normal, - Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"), + Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761", + Some("replace this attribute with `#[may_dangle]`")), "dropck_parametricity", "unsafe_destructor_blind_to_params has been replaced by \ may_dangle and will be removed in the future", @@ -1136,9 +1144,10 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { ("panic_implementation", Normal, Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/44489\ - #issuecomment-415140224"), + #issuecomment-415140224", + Some("replace this attribute with `#[panic_handler]`")), "panic_implementation", - "This attribute was renamed to `panic_handler`", + "this attribute was renamed to `panic_handler`", cfg_fn!(panic_implementation))), // RFC 2070 @@ -1879,10 +1888,7 @@ fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { // cannot be kept in identifiers, so it's kept in paths instead and we take it from // there while keeping location info from the ident span. let span = segment.ident.span.with_ctxt(path.span.ctxt()); - if segment.ident.name == keywords::Crate.name() { - gate_feature_post!(&self, crate_in_paths, span, - "`crate` in paths is experimental"); - } else if segment.ident.name == keywords::Extern.name() { + if segment.ident.name == keywords::Extern.name() { gate_feature_post!(&self, extern_in_paths, span, "`extern` in paths is experimental"); } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 2aaab6aaa16..68b46841718 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -46,7 +46,7 @@ extern crate serialize as rustc_serialize; // used by deriving use rustc_data_structures::sync::Lock; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bit_set::GrowableBitSet; pub use rustc_data_structures::small_vec::OneVector; pub use rustc_data_structures::thin_vec::ThinVec; use ast::AttrId; @@ -82,8 +82,8 @@ macro_rules! unwrap_or { } pub struct Globals { - used_attrs: Lock>, - known_attrs: Lock>, + used_attrs: Lock>, + known_attrs: Lock>, syntax_pos_globals: syntax_pos::Globals, } @@ -92,8 +92,8 @@ fn new() -> Globals { Globals { // We have no idea how many attributes their will be, so just // initiate the vectors with 0 bits. We'll grow them as necessary. - used_attrs: Lock::new(BitVector::new()), - known_attrs: Lock::new(BitVector::new()), + used_attrs: Lock::new(GrowableBitSet::new_empty()), + known_attrs: Lock::new(GrowableBitSet::new_empty()), syntax_pos_globals: syntax_pos::Globals::new(), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f57fca2cfcf..6ec1ad969ee 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -732,6 +732,22 @@ fn tokens_to_string(tokens: &[TokenType]) -> String { format!("expected {} here", expect))) }; let mut err = self.fatal(&msg_exp); + if self.token.is_ident_named("and") { + err.span_suggestion_short_with_applicability( + self.span, + "use `&&` instead of `and` for the boolean operator", + "&&".to_string(), + Applicability::MaybeIncorrect, + ); + } + if self.token.is_ident_named("or") { + err.span_suggestion_short_with_applicability( + self.span, + "use `||` instead of `or` for the boolean operator", + "||".to_string(), + Applicability::MaybeIncorrect, + ); + } let sp = if self.token == token::Token::Eof { // This is EOF, don't want to point at the following char, but rather the last token self.prev_span @@ -3866,7 +3882,12 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec PResult<'a, P> { e.span_label(sp, "expected `{`"); } + if self.token.is_ident_named("and") { + e.span_suggestion_short_with_applicability( + self.span, + "use `&&` instead of `and` for the boolean operator", + "&&".to_string(), + Applicability::MaybeIncorrect, + ); + } + if self.token.is_ident_named("or") { + e.span_suggestion_short_with_applicability( + self.span, + "use `||` instead of `or` for the boolean operator", + "||".to_string(), + Applicability::MaybeIncorrect, + ); + } + // Check to see if the user has written something like // // if (cond) diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index b86d19ba3ce..bb47d9b535b 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -38,7 +38,7 @@ use std::fmt::{self, Display, Debug}; use std::iter::FromIterator; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use std::{mem, ptr, slice, vec}; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -103,6 +103,12 @@ fn deref(&self) -> &T { } } +impl DerefMut for P { + fn deref_mut(&mut self) -> &mut T { + &mut self.ptr + } +} + impl Clone for P { fn clone(&self) -> P { P((**self).clone()) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index efe9c2cefde..31e608de1f8 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -996,9 +996,10 @@ macro_rules! check_foreign { )); } if suggestions.len() > 0 { - diag.multipart_suggestion( + diag.multipart_suggestion_with_applicability( "format specifiers use curly braces", suggestions, + Applicability::MachineApplicable, ); } }}; diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index be3485cfa7c..8ddfb1d9cba 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -49,7 +49,7 @@ pub fn expand_test_or_bench( // If we're not in test configuration, remove the annotated item if !cx.ecfg.should_test { return vec![]; } - let item = + let mut item = if let Annotatable::Item(i) = item { i } else { cx.parse_sess.span_diagnostic.span_fatal(item.span(), @@ -192,6 +192,12 @@ pub fn expand_test_or_bench( debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); + // Temporarily add another marker to the original item for error reporting + let marker2 = cx.attribute( + attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker2")) + ); + item.attrs.push(marker2); + vec![ // Access to libtest under a gensymed name Annotatable::Item(test_extern), diff --git a/src/llvm b/src/llvm index 5a081f03633..caddcd9b9dc 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 5a081f0363340dd895d0958955d0c84661f60f05 +Subproject commit caddcd9b9dc9479a20908d93c3e47c49b021379e diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 29b7d508f1c..f8ff3d37fd2 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-09-11 +2018-09-16 diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs deleted file mode 100644 index 679cb772868..00000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_attribute] -pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs deleted file mode 100644 index 6484725814a..00000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro] -pub fn bang_proc_macro(input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs b/src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs deleted file mode 100644 index 0fcb9efc1c9..00000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:attr_proc_macro.rs - -#[macro_use] extern crate attr_proc_macro; - -#[attr_proc_macro] -//~^ ERROR: attribute procedural macros cannot be imported with `#[macro_use]` -struct Foo; - -fn main() { - let _ = Foo; -} diff --git a/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs b/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs deleted file mode 100644 index be5b8c39f1d..00000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:bang_proc_macro.rs - -#![feature(proc_macro_non_items)] - -#[macro_use] -extern crate bang_proc_macro; - -fn main() { - bang_proc_macro!(println!("Hello, world!")); - //~^ ERROR: procedural macros cannot be imported with `#[macro_use]` -} diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs index 215d51c2270..83bbb7c13c4 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs @@ -16,12 +16,12 @@ #[macro_use] extern crate derive_b; -#[derive(B)] #[B] //~ ERROR `B` is a derive mode #[C] #[B(D)] #[B(E = "foo")] #[B(arbitrary tokens)] +#[derive(B)] struct B; fn main() {} diff --git a/src/test/run-make-fulldeps/extern-prelude/Makefile b/src/test/run-make-fulldeps/extern-prelude/Makefile index aa8158c6eb3..69af01ccf03 100644 --- a/src/test/run-make-fulldeps/extern-prelude/Makefile +++ b/src/test/run-make-fulldeps/extern-prelude/Makefile @@ -7,6 +7,5 @@ all: $(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib $(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib $(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib - $(RUSTC) feature-gate.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "access to extern crates through prelude is experimental" $(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import" $(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve" diff --git a/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs b/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs deleted file mode 100644 index 49763f3ba6a..00000000000 --- a/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let s = ep_lib::S; // Feature error -} diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile index 6a67b5862a8..2b931d89f1f 100644 --- a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -1,9 +1,11 @@ -include ../tools.mk all: extern_absolute_paths.rs extern_in_paths.rs krate2 - $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 + $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 \ + -Z unstable-options --extern krate2 cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py - $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 + $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 \ + -Z unstable-options --extern krate2 cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py krate2: krate2.rs diff --git a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs index 6a706bdb9b2..6ae06f2d561 100644 --- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // ignore-cross-compile #![feature(rustc_private)] diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr b/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr new file mode 100644 index 00000000000..ba956e4c132 --- /dev/null +++ b/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr @@ -0,0 +1,6 @@ +warning: `#[derive]` for custom traits is deprecated and will be removed in the future. Prefer using procedural macro custom derive. + --> $DIR/custom-derive-partial-eq.rs:17:10 + | +LL | #[derive(CustomPartialEq)] // Check that this is not a stability error. + | ^^^^^^^^^^^^^^^ + diff --git a/src/test/run-pass-fulldeps/derive-no-std-not-supported.rs b/src/test/run-pass-fulldeps/derive-no-std-not-supported.rs index a0747e0fbf5..1e42355f834 100644 --- a/src/test/run-pass-fulldeps/derive-no-std-not-supported.rs +++ b/src/test/run-pass-fulldeps/derive-no-std-not-supported.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #![feature(rustc_private)] #![no_std] diff --git a/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs b/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs index 4c5b3259902..8b56ade21f9 100644 --- a/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs +++ b/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] #![feature(box_syntax)] #![feature(rustc_private)] extern crate serialize; +use serialize as rustc_serialize; use serialize::{Encodable, Decodable}; use serialize::json; -#[derive(Encodable, Decodable)] +#[derive(RustcEncodable, RustcDecodable)] struct A { foo: Box<[bool]>, } diff --git a/src/test/run-pass-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass-fulldeps/deriving-encodable-decodable-cell-refcell.rs index 6e5eb86c584..15edd4d4950 100644 --- a/src/test/run-pass-fulldeps/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/run-pass-fulldeps/deriving-encodable-decodable-cell-refcell.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // This briefly tests the capability of `Cell` and `RefCell` to implement the // `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]` @@ -15,17 +16,18 @@ #![feature(rustc_private)] extern crate serialize; +use serialize as rustc_serialize; use std::cell::{Cell, RefCell}; use serialize::{Encodable, Decodable}; use serialize::json; -#[derive(Encodable, Decodable)] +#[derive(RustcEncodable, RustcDecodable)] struct A { baz: isize } -#[derive(Encodable, Decodable)] +#[derive(RustcEncodable, RustcDecodable)] struct B { foo: Cell, bar: RefCell, diff --git a/src/test/run-pass-fulldeps/deriving-global.rs b/src/test/run-pass-fulldeps/deriving-global.rs index e9678732804..b95c947d215 100644 --- a/src/test/run-pass-fulldeps/deriving-global.rs +++ b/src/test/run-pass-fulldeps/deriving-global.rs @@ -11,6 +11,7 @@ #![feature(rustc_private)] extern crate serialize; +use serialize as rustc_serialize; mod submod { // if any of these are implemented without global calls for any @@ -20,21 +21,21 @@ mod submod { Hash, Clone, Debug, - Encodable, Decodable)] + RustcEncodable, RustcDecodable)] enum A { A1(usize), A2(isize) } #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, - Encodable, Decodable)] + RustcEncodable, RustcDecodable)] struct B { x: usize, y: isize } #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, - Encodable, Decodable)] + RustcEncodable, RustcDecodable)] struct C(usize, isize); } diff --git a/src/test/run-pass-fulldeps/deriving-hygiene.rs b/src/test/run-pass-fulldeps/deriving-hygiene.rs index 532f2456599..1deeb242437 100644 --- a/src/test/run-pass-fulldeps/deriving-hygiene.rs +++ b/src/test/run-pass-fulldeps/deriving-hygiene.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] #![feature(rustc_private)] extern crate serialize; +use serialize as rustc_serialize; pub const other: u8 = 1; pub const f: u8 = 1; @@ -18,7 +20,7 @@ pub const state: u8 = 1; pub const cmp: u8 = 1; -#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,Decodable,Encodable,Hash)] +#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,RustcDecodable,RustcEncodable,Hash)] struct Foo {} fn main() { diff --git a/src/test/run-pass-fulldeps/dropck_tarena_sound_drop.rs b/src/test/run-pass-fulldeps/dropck_tarena_sound_drop.rs index db30bfbf747..48f54188796 100644 --- a/src/test/run-pass-fulldeps/dropck_tarena_sound_drop.rs +++ b/src/test/run-pass-fulldeps/dropck_tarena_sound_drop.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unknown_lints)] // Check that an arena (TypedArena) can carry elements whose drop // methods might access borrowed data, as long as the borrowed data // has lifetime that strictly outlives the arena itself. diff --git a/src/test/run-pass-fulldeps/issue-11881.rs b/src/test/run-pass-fulldeps/issue-11881.rs index 4f419e70074..5121ecd6cf3 100644 --- a/src/test/run-pass-fulldeps/issue-11881.rs +++ b/src/test/run-pass-fulldeps/issue-11881.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_imports)] #![feature(rustc_private)] extern crate serialize; +use serialize as rustc_serialize; use std::io::Cursor; use std::io::prelude::*; @@ -22,12 +26,12 @@ use serialize::json; use serialize::opaque; -#[derive(Encodable)] +#[derive(RustcEncodable)] struct Foo { baz: bool, } -#[derive(Encodable)] +#[derive(RustcEncodable)] struct Bar { froboz: usize, } diff --git a/src/test/run-pass-fulldeps/issue-14021.rs b/src/test/run-pass-fulldeps/issue-14021.rs index 907967d115d..5426dd94637 100644 --- a/src/test/run-pass-fulldeps/issue-14021.rs +++ b/src/test/run-pass-fulldeps/issue-14021.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] +#![allow(unused_imports)] #![feature(rustc_private)] extern crate serialize; +extern crate serialize as rustc_serialize; use serialize::{Encodable, Decodable}; use serialize::json; -#[derive(Encodable, Decodable, PartialEq, Debug)] +#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)] struct UnitLikeStruct; pub fn main() { diff --git a/src/test/run-pass-fulldeps/issue-15149.rs b/src/test/run-pass-fulldeps/issue-15149.rs index 15ac1d55cc8..362aeabd60e 100644 --- a/src/test/run-pass-fulldeps/issue-15149.rs +++ b/src/test/run-pass-fulldeps/issue-15149.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] // no-prefer-dynamic // ignore-cross-compile diff --git a/src/test/run-pass-fulldeps/issue-15924.rs b/src/test/run-pass-fulldeps/issue-15924.rs index 0c208773884..717a35707b4 100644 --- a/src/test/run-pass-fulldeps/issue-15924.rs +++ b/src/test/run-pass-fulldeps/issue-15924.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] +#![allow(unused_must_use)] // pretty-expanded FIXME #23616 #![feature(rustc_private)] diff --git a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs index 03311d76e46..016f6139529 100644 --- a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs +++ b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_imports)] // ignore-cross-compile #![feature(quote, rustc_private)] diff --git a/src/test/run-pass-fulldeps/issue-24972.rs b/src/test/run-pass-fulldeps/issue-24972.rs index ae7eb84d3e8..6abdf98bb38 100644 --- a/src/test/run-pass-fulldeps/issue-24972.rs +++ b/src/test/run-pass-fulldeps/issue-24972.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass-fulldeps/issue-2804.rs b/src/test/run-pass-fulldeps/issue-2804.rs index f999d2d0ed9..2e1104afae0 100644 --- a/src/test/run-pass-fulldeps/issue-2804.rs +++ b/src/test/run-pass-fulldeps/issue-2804.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] #![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass-fulldeps/issue-4016.rs b/src/test/run-pass-fulldeps/issue-4016.rs index bc3fa162e02..2d72b42a5bd 100644 --- a/src/test/run-pass-fulldeps/issue-4016.rs +++ b/src/test/run-pass-fulldeps/issue-4016.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #![feature(rustc_private)] diff --git a/src/test/run-pass-fulldeps/issue-40663.rs b/src/test/run-pass-fulldeps/issue-40663.rs index 8cb9dc4a1b6..8633e906082 100644 --- a/src/test/run-pass-fulldeps/issue-40663.rs +++ b/src/test/run-pass-fulldeps/issue-40663.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // aux-build:custom_derive_plugin.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs b/src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs index 86d7cd54d97..5d00b594434 100644 --- a/src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs +++ b/src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(plugin_as_library)] +#![allow(unused_imports)] // aux-build:macro_crate_test.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs b/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs index 9245e85edd6..6e8314b9680 100644 --- a/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs +++ b/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(plugin_as_library)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] // aux-build:macro_crate_test.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs index 06f78b10e5e..c3e7787cf7f 100644 --- a/src/test/run-pass-fulldeps/macro-crate.rs +++ b/src/test/run-pass-fulldeps/macro-crate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(plugin_as_library)] +#![allow(dead_code)] // aux-build:macro_crate_test.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/macro-quote-cond.rs b/src/test/run-pass-fulldeps/macro-quote-cond.rs index 3eb7e8cc9a4..4c36f097ec1 100644 --- a/src/test/run-pass-fulldeps/macro-quote-cond.rs +++ b/src/test/run-pass-fulldeps/macro-quote-cond.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_parens)] // aux-build:cond_plugin.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/call-site.rs b/src/test/run-pass-fulldeps/proc-macro/call-site.rs index dfe97eb587c..9d2120e6764 100644 --- a/src/test/run-pass-fulldeps/proc-macro/call-site.rs +++ b/src/test/run-pass-fulldeps/proc-macro/call-site.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] +#![allow(unused_imports)] // aux-build:call-site.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs index 93023f8f8ed..e7e8b3d665e 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // aux-build:derive-attr-cfg.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs index ba5a639a759..64ad57107c7 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(path_statements)] +#![allow(dead_code)] // aux-build:derive-same-struct.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.stdout b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.stdout new file mode 100644 index 00000000000..77605de5e33 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.stdout @@ -0,0 +1 @@ +input1: "struct A;" diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs b/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs index 0df0288216e..9c2ba481f5e 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // aux-build:derive-two-attrs.rs extern crate derive_two_attrs as foo; diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-union.rs b/src/test/run-pass-fulldeps/proc-macro/derive-union.rs index 71807e21d96..298a652aacc 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-union.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-union.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] // aux-build:derive-union.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs b/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs index 38a2716aee7..2b0a57dafef 100644 --- a/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs +++ b/src/test/run-pass-fulldeps/proc-macro/empty-crate.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // aux-build:empty-crate.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs b/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs index 579e8c33773..2d15b4e60b4 100644 --- a/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs +++ b/src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_macros)] // aux-build:hygiene_example_codegen.rs // aux-build:hygiene_example.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs b/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs index 3fc7446815e..f7221092601 100644 --- a/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs +++ b/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // aux-build:issue-39889.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs index 410faaeb3ee..04659166575 100644 --- a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs +++ b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(path_statements)] // aux-build:issue-50061.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/lifetimes.rs b/src/test/run-pass-fulldeps/proc-macro/lifetimes.rs index c73441e30e6..79d6d27dc59 100644 --- a/src/test/run-pass-fulldeps/proc-macro/lifetimes.rs +++ b/src/test/run-pass-fulldeps/proc-macro/lifetimes.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] // aux-build:lifetimes.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/load-two.rs b/src/test/run-pass-fulldeps/proc-macro/load-two.rs index 67c12377814..cf1e076f270 100644 --- a/src/test/run-pass-fulldeps/proc-macro/load-two.rs +++ b/src/test/run-pass-fulldeps/proc-macro/load-two.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(path_statements)] +#![allow(dead_code)] // aux-build:derive-atob.rs // aux-build:derive-ctod.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/smoke.rs b/src/test/run-pass-fulldeps/proc-macro/smoke.rs index 54d651df1f9..49011e19a51 100644 --- a/src/test/run-pass-fulldeps/proc-macro/smoke.rs +++ b/src/test/run-pass-fulldeps/proc-macro/smoke.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(path_statements)] // aux-build:derive-a.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs index c9056e08d44..db52aa5d3a6 100644 --- a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // aux-build:derive-nothing.rs // ignore-stage1 diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 55fed8693a0..ec12ad17e8f 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // ignore-cross-compile #![feature(quote, rustc_private)] diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 8e6a69cb584..7f46e0928a2 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] // ignore-cross-compile #![feature(quote, rustc_private)] diff --git a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs index d3be1ddcb8c..7e85becfc3c 100644 --- a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs +++ b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // ignore-cross-compile #![feature(quote, rustc_private)] #![deny(unused_variables)] diff --git a/src/test/run-pass-fulldeps/regions-mock-tcx.rs b/src/test/run-pass-fulldeps/regions-mock-tcx.rs index 670f5380d81..013c331d0fd 100644 --- a/src/test/run-pass-fulldeps/regions-mock-tcx.rs +++ b/src/test/run-pass-fulldeps/regions-mock-tcx.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_imports)] // Test a sample usage pattern for regions. Makes use of the // following features: diff --git a/src/test/run-pass-fulldeps/rename-directory.rs b/src/test/run-pass-fulldeps/rename-directory.rs index 417707e8932..099f3e58c6c 100644 --- a/src/test/run-pass-fulldeps/rename-directory.rs +++ b/src/test/run-pass-fulldeps/rename-directory.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(unused_imports)] // This test can't be a unit test in std, // because it needs TempDir, which is in extra diff --git a/src/test/run-pass/abort-on-c-abi.rs b/src/test/run-pass/abort-on-c-abi.rs index ef368ed604b..17b2ee39c88 100644 --- a/src/test/run-pass/abort-on-c-abi.rs +++ b/src/test/run-pass/abort-on-c-abi.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that // we never unwind through them. diff --git a/src/test/run-pass/alias-uninit-value.rs b/src/test/run-pass/alias-uninit-value.rs index 77b9efb0012..5c87840fe1e 100644 --- a/src/test/run-pass/alias-uninit-value.rs +++ b/src/test/run-pass/alias-uninit-value.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] + // Regression test for issue #374 diff --git a/src/test/run-pass/align-with-extern-c-fn.rs b/src/test/run-pass/align-with-extern-c-fn.rs index 6f89c5d377f..92ae68fb6a3 100644 --- a/src/test/run-pass/align-with-extern-c-fn.rs +++ b/src/test/run-pass/align-with-extern-c-fn.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] +#![allow(unused_variables)] + // #45662 #![feature(repr_align)] diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs index c1f75d5ee74..7188496dab9 100644 --- a/src/test/run-pass/alignment-gep-tup-like-1.rs +++ b/src/test/run-pass/alignment-gep-tup-like-1.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] + #![feature(box_syntax)] struct pair { diff --git a/src/test/run-pass/alloca-from-derived-tydesc.rs b/src/test/run-pass/alloca-from-derived-tydesc.rs index 23a1e799801..7895e89d586 100644 --- a/src/test/run-pass/alloca-from-derived-tydesc.rs +++ b/src/test/run-pass/alloca-from-derived-tydesc.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] + // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs index f15b013c07b..a62bd67a5ac 100644 --- a/src/test/run-pass/allocator-alloc-one.rs +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] + #![feature(allocator_api, nonnull)] use std::alloc::{Alloc, Global, Layout, handle_alloc_error}; diff --git a/src/test/run-pass/asm-in-moved.rs b/src/test/run-pass/asm-in-moved.rs index 246dd83fbef..debfcc5c552 100644 --- a/src/test/run-pass/asm-in-moved.rs +++ b/src/test/run-pass/asm-in-moved.rs @@ -12,6 +12,7 @@ //[mir]compile-flags: -Z borrowck=mir #![feature(asm)] +#![allow(dead_code)] use std::cell::Cell; diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index f692f57abb9..3301e6a4637 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -12,8 +12,7 @@ #![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)] -use std::pin::PinBox; -use std::pin::PinMut; +use std::pin::Pin; use std::future::Future; use std::sync::{ Arc, @@ -49,7 +48,7 @@ fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } impl Future for WakeOnceThenComplete { type Output = (); - fn poll(mut self: PinMut, cx: &mut Context) -> Poll<()> { + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> { if self.0 { Poll::Ready(()) } else { @@ -148,16 +147,16 @@ fn test_future_yields_once_then_returns(f: F) F: FnOnce(u8) -> Fut, Fut: Future, { - let mut fut = PinBox::new(f(9)); + let mut fut = Box::pinned(f(9)); let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); let waker = local_waker_from_nonlocal(counter.clone()); let spawner = &mut NoopSpawner; let cx = &mut Context::new(&waker, spawner); assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); - assert_eq!(Poll::Pending, fut.as_pin_mut().poll(cx)); + assert_eq!(Poll::Pending, fut.as_mut().poll(cx)); assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); - assert_eq!(Poll::Ready(9), fut.as_pin_mut().poll(cx)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(cx)); } fn main() { diff --git a/src/test/run-pass/atomic-access-bool.rs b/src/test/run-pass/atomic-access-bool.rs index 286c92ce50e..1d8923af479 100644 --- a/src/test/run-pass/atomic-access-bool.rs +++ b/src/test/run-pass/atomic-access-bool.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] #![feature(atomic_access)] use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use std::sync::atomic::Ordering::*; diff --git a/src/test/run-pass/atomic-compare_exchange.rs b/src/test/run-pass/atomic-compare_exchange.rs index 2f33eb9ca40..5829f764eba 100644 --- a/src/test/run-pass/atomic-compare_exchange.rs +++ b/src/test/run-pass/atomic-compare_exchange.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] + #![feature(extended_compare_and_swap)] use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT}; use std::sync::atomic::Ordering::*; diff --git a/src/test/run-pass/atomic-print.rs b/src/test/run-pass/atomic-print.rs index 2d478e954e7..25f4c6fd10b 100644 --- a/src/test/run-pass/atomic-print.rs +++ b/src/test/run-pass/atomic-print.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(deprecated)] // ignore-cloudabi no process support // ignore-emscripten no threads support diff --git a/src/test/run-pass/attr-before-view-item.rs b/src/test/run-pass/attr-before-view-item.rs index 2a86489c69a..4ea78d352e3 100644 --- a/src/test/run-pass/attr-before-view-item.rs +++ b/src/test/run-pass/attr-before-view-item.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attributes)] + // pretty-expanded FIXME #23616 #![feature(custom_attribute, test)] diff --git a/src/test/run-pass/attr-before-view-item2.rs b/src/test/run-pass/attr-before-view-item2.rs index c8683f2d147..34a8b62f9fc 100644 --- a/src/test/run-pass/attr-before-view-item2.rs +++ b/src/test/run-pass/attr-before-view-item2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attributes)] + // pretty-expanded FIXME #23616 #![feature(custom_attribute, test)] diff --git a/src/test/run-pass/attr-mix-new.rs b/src/test/run-pass/attr-mix-new.rs index bcfb4b330f5..5b89cec70c0 100644 --- a/src/test/run-pass/attr-mix-new.rs +++ b/src/test/run-pass/attr-mix-new.rs @@ -7,6 +7,10 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +#![allow(unused_attributes)] +#![allow(unknown_lints)] + // pretty-expanded FIXME #23616 #![allow(unused_attribute)] diff --git a/src/test/run-pass/attr-on-generic-formals.rs b/src/test/run-pass/attr-on-generic-formals.rs index e87b9e3d82a..827da72bc44 100644 --- a/src/test/run-pass/attr-on-generic-formals.rs +++ b/src/test/run-pass/attr-on-generic-formals.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attributes)] + // This test ensures we can attach attributes to the formals in all // places where generic parameter lists occur, assuming appropriate // feature gates are enabled. diff --git a/src/test/run-pass/augmented-assignments.rs b/src/test/run-pass/augmented-assignments.rs index 3ed9e8548dc..b8bfad8cfcb 100644 --- a/src/test/run-pass/augmented-assignments.rs +++ b/src/test/run-pass/augmented-assignments.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] #![deny(unused_assignments)] use std::mem; diff --git a/src/test/run-pass/auto-instantiate.rs b/src/test/run-pass/auto-instantiate.rs index 4a1bfa3eb42..0fe347fc43c 100644 --- a/src/test/run-pass/auto-instantiate.rs +++ b/src/test/run-pass/auto-instantiate.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #[derive(Debug)] struct Pair { a: T, b: U } struct Triple { x: isize, y: isize, z: isize } diff --git a/src/test/run-pass/auto-is-contextual.rs b/src/test/run-pass/auto-is-contextual.rs index ad433cc26a7..efddcaa14d3 100644 --- a/src/test/run-pass/auto-is-contextual.rs +++ b/src/test/run-pass/auto-is-contextual.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(path_statements)] +#![allow(dead_code)] macro_rules! auto { () => (struct S;) } diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index 2b8fcd303b6..0b2098b0f05 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] // Binop corner cases fn test_nil() { diff --git a/src/test/run-pass/blind-item-local-shadow.rs b/src/test/run-pass/blind-item-local-shadow.rs index bb654b1a20b..6066bc32b26 100644 --- a/src/test/run-pass/blind-item-local-shadow.rs +++ b/src/test/run-pass/blind-item-local-shadow.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_imports)] mod bar { pub fn foo() -> bool { true } } diff --git a/src/test/run-pass/block-arg-call-as.rs b/src/test/run-pass/block-arg-call-as.rs index 73cba2e4e0a..342f67ae44f 100644 --- a/src/test/run-pass/block-arg-call-as.rs +++ b/src/test/run-pass/block-arg-call-as.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_snake_case)] fn asBlock(f: F) -> usize where F: FnOnce() -> usize { return f(); diff --git a/src/test/run-pass/block-expr-precedence.rs b/src/test/run-pass/block-expr-precedence.rs index ac8f5012573..acb0f2dd298 100644 --- a/src/test/run-pass/block-expr-precedence.rs +++ b/src/test/run-pass/block-expr-precedence.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(unused_parens)] // This test has some extra semis in it that the pretty-printer won't // reproduce so we don't want to automatically reformat it diff --git a/src/test/run-pass/builtin-clone-unwind.rs b/src/test/run-pass/builtin-clone-unwind.rs index 7e7c5ee4125..6f8cdd1b4fc 100644 --- a/src/test/run-pass/builtin-clone-unwind.rs +++ b/src/test/run-pass/builtin-clone-unwind.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] +#![allow(unused_imports)] // ignore-wasm32-bare compiled with panic=abort by default // Test that builtin implementations of `Clone` cleanup everything diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index 3259b1cc067..287e6829487 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // aux-build:trait_superkinds_in_metadata.rs diff --git a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs index 6bc81f4a36b..84601f68d16 100644 --- a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Tests that even when a type parameter doesn't implement a required // super-builtin-kind of a trait, if the type parameter is never used, // the type can implement the trait anyway. diff --git a/src/test/run-pass/cast.rs b/src/test/run-pass/cast.rs index 80fa5362a8b..b88854cd7fa 100644 --- a/src/test/run-pass/cast.rs +++ b/src/test/run-pass/cast.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_assignments)] +#![allow(unused_variables)] pub fn main() { let i: isize = 'Q' as isize; diff --git a/src/test/run-pass/cell-does-not-clone.rs b/src/test/run-pass/cell-does-not-clone.rs index c1fcf496546..9f26ee818e6 100644 --- a/src/test/run-pass/cell-does-not-clone.rs +++ b/src/test/run-pass/cell-does-not-clone.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] use std::cell::Cell; diff --git a/src/test/run-pass/check-static-recursion-foreign.rs b/src/test/run-pass/check-static-recursion-foreign.rs index 9c87f2ca682..a95870c2b27 100644 --- a/src/test/run-pass/check-static-recursion-foreign.rs +++ b/src/test/run-pass/check-static-recursion-foreign.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Static recursion check shouldn't fail when given a foreign item (#18279) // aux-build:check_static_recursion_foreign_helper.rs diff --git a/src/test/run-pass/cleanup-arm-conditional.rs b/src/test/run-pass/cleanup-arm-conditional.rs index dd900c56b40..6ff3aff45cb 100644 --- a/src/test/run-pass/cleanup-arm-conditional.rs +++ b/src/test/run-pass/cleanup-arm-conditional.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] +#![allow(unused_imports)] // Test that cleanup scope for temporaries created in a match // arm is confined to the match arm itself. diff --git a/src/test/run-pass/cleanup-rvalue-for-scope.rs b/src/test/run-pass/cleanup-rvalue-for-scope.rs index f69a0332cc4..4f8ded9012f 100644 --- a/src/test/run-pass/cleanup-rvalue-for-scope.rs +++ b/src/test/run-pass/cleanup-rvalue-for-scope.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_snake_case)] +#![allow(dead_code)] +#![allow(unused_variables)] // Test that the lifetime of rvalues in for loops is extended // to the for loop itself. diff --git a/src/test/run-pass/cleanup-rvalue-scopes.rs b/src/test/run-pass/cleanup-rvalue-scopes.rs index b5bf35a7006..8cf014a4d2a 100644 --- a/src/test/run-pass/cleanup-rvalue-scopes.rs +++ b/src/test/run-pass/cleanup-rvalue-scopes.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_snake_case)] +#![allow(unused_variables)] // Test that destructors for rvalue temporaries run either at end of // statement or end of block, as appropriate given the temporary // lifetime rules. diff --git a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs index ae455d916b6..90b2031afd4 100644 --- a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs +++ b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_variables)] // Test cleanup of rvalue temporary that occurs while `box` construction // is in progress. This scenario revealed a rather terrible bug. The // ingredients are: diff --git a/src/test/run-pass/clone-with-exterior.rs b/src/test/run-pass/clone-with-exterior.rs index 6ac7acd2a6b..0358eec0d76 100644 --- a/src/test/run-pass/clone-with-exterior.rs +++ b/src/test/run-pass/clone-with-exterior.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // ignore-emscripten no threads support #![feature(box_syntax)] diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs index ba700e4e326..44778517c44 100644 --- a/src/test/run-pass/close-over-big-then-small-data.rs +++ b/src/test/run-pass/close-over-big-then-small-data.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // If we use GEPi rather than GEP_tup_like when // storing closure data (as we used to do), the u64 would // overwrite the u16. diff --git a/src/test/run-pass/collections-const-new.rs b/src/test/run-pass/collections-const-new.rs index 4003c2ec4f7..462dc42dbc2 100644 --- a/src/test/run-pass/collections-const-new.rs +++ b/src/test/run-pass/collections-const-new.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Test several functions can be used for constants // 1. Vec::new() // 2. String::new() diff --git a/src/test/run-pass/command-before-exec.rs b/src/test/run-pass/command-before-exec.rs index c4fc9ee53fd..5d8bc31c2a3 100644 --- a/src/test/run-pass/command-before-exec.rs +++ b/src/test/run-pass/command-before-exec.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // ignore-windows - this is a unix-specific test // ignore-cloudabi no processes // ignore-emscripten no processes diff --git a/src/test/run-pass/command-exec.rs b/src/test/run-pass/command-exec.rs index d6d0c2b36f6..46b409fb13a 100644 --- a/src/test/run-pass/command-exec.rs +++ b/src/test/run-pass/command-exec.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // ignore-windows - this is a unix-specific test // ignore-pretty issue #37199 // ignore-cloudabi no processes diff --git a/src/test/run-pass/complex.rs b/src/test/run-pass/complex.rs index 6bb9503c2b0..b31f4d39f82 100644 --- a/src/test/run-pass/complex.rs +++ b/src/test/run-pass/complex.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unconditional_recursion)] +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unused_mut)] diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index eaec9b1926a..aaf017c0ad3 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(stable_features)] +#![allow(deprecated)] +#![allow(unused_imports)] // compile-flags:--test // ignore-cloudabi no processes // ignore-emscripten no processes diff --git a/src/test/run-pass/crt-static-off-works.rs b/src/test/run-pass/crt-static-off-works.rs index c94c877c12c..14f5913e377 100644 --- a/src/test/run-pass/crt-static-off-works.rs +++ b/src/test/run-pass/crt-static-off-works.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // compile-flags:-C target-feature=-crt-static -Z unstable-options // ignore-musl - requires changing the linker which is hard diff --git a/src/test/run-pass/crt-static-on-works.rs b/src/test/run-pass/crt-static-on-works.rs index ae8e5f62970..dbc483241ab 100644 --- a/src/test/run-pass/crt-static-on-works.rs +++ b/src/test/run-pass/crt-static-on-works.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // compile-flags:-C target-feature=+crt-static -Z unstable-options #![feature(cfg_target_feature)] diff --git a/src/test/run-pass/default-method-simple.rs b/src/test/run-pass/default-method-simple.rs index 61de804a80a..d4e25bb5c3c 100644 --- a/src/test/run-pass/default-method-simple.rs +++ b/src/test/run-pass/default-method-simple.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] trait Foo { fn f(&self) { diff --git a/src/test/run-pass/defaults-well-formedness.rs b/src/test/run-pass/defaults-well-formedness.rs index 9b06bf837ae..fce5e911c57 100644 --- a/src/test/run-pass/defaults-well-formedness.rs +++ b/src/test/run-pass/defaults-well-formedness.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] trait Trait {} struct Foo(U, V) where U: Trait; diff --git a/src/test/run-pass/discriminant_value.rs b/src/test/run-pass/discriminant_value.rs index 13257529ed9..06d4f16826f 100644 --- a/src/test/run-pass/discriminant_value.rs +++ b/src/test/run-pass/discriminant_value.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] #![feature(core, core_intrinsics)] extern crate core; diff --git a/src/test/run-pass/diverging-fallback-control-flow.rs b/src/test/run-pass/diverging-fallback-control-flow.rs index 723a98bcdfa..9f54f50e540 100644 --- a/src/test/run-pass/diverging-fallback-control-flow.rs +++ b/src/test/run-pass/diverging-fallback-control-flow.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(unreachable_code)] // Test various cases where we permit an unconstrained variable // to fallback based on control-flow. // diff --git a/src/test/run-pass/diverging-fallback-method-chain.rs b/src/test/run-pass/diverging-fallback-method-chain.rs index 664a329c228..195c55d374b 100644 --- a/src/test/run-pass/diverging-fallback-method-chain.rs +++ b/src/test/run-pass/diverging-fallback-method-chain.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // Test a regression found when building compiler. The `produce()` // error type `T` winds up getting unified with result of `x.parse()`; // the type of the closure given to `unwrap_or_else` needs to be diff --git a/src/test/run-pass/double-ref.rs b/src/test/run-pass/double-ref.rs index 13ce6a07e36..9fa3fbca071 100644 --- a/src/test/run-pass/double-ref.rs +++ b/src/test/run-pass/double-ref.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 fn check_expr() { diff --git a/src/test/run-pass/early-ret-binop-add.rs b/src/test/run-pass/early-ret-binop-add.rs index 0a490466ef7..c4401781f59 100644 --- a/src/test/run-pass/early-ret-binop-add.rs +++ b/src/test/run-pass/early-ret-binop-add.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unreachable_code)] // pretty-expanded FIXME #23616 use std::ops::Add; diff --git a/src/test/run-pass/early-vtbl-resolution.rs b/src/test/run-pass/early-vtbl-resolution.rs index 2d2cf6fbf0a..985ed08d34d 100644 --- a/src/test/run-pass/early-vtbl-resolution.rs +++ b/src/test/run-pass/early-vtbl-resolution.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 trait thing { diff --git a/src/test/run-pass/edition-keywords-2015-2015.rs b/src/test/run-pass/edition-keywords-2015-2015.rs index 1751eacc6b7..b805b01ae39 100644 --- a/src/test/run-pass/edition-keywords-2015-2015.rs +++ b/src/test/run-pass/edition-keywords-2015-2015.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] +#![allow(unused_assignments)] +#![allow(unused_variables)] // edition:2015 // aux-build:edition-kw-macro-2015.rs diff --git a/src/test/run-pass/edition-keywords-2015-2018.rs b/src/test/run-pass/edition-keywords-2015-2018.rs index f2794a4b8d8..1e3d0c5f777 100644 --- a/src/test/run-pass/edition-keywords-2015-2018.rs +++ b/src/test/run-pass/edition-keywords-2015-2018.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] +#![allow(unused_assignments)] +#![allow(unused_variables)] // edition:2015 // aux-build:edition-kw-macro-2018.rs diff --git a/src/test/run-pass/edition-keywords-2018-2015.rs b/src/test/run-pass/edition-keywords-2018-2015.rs index 7d5de00cdb8..9b2e49c5111 100644 --- a/src/test/run-pass/edition-keywords-2018-2015.rs +++ b/src/test/run-pass/edition-keywords-2018-2015.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_assignments)] // edition:2018 // aux-build:edition-kw-macro-2015.rs diff --git a/src/test/run-pass/edition-keywords-2018-2018.rs b/src/test/run-pass/edition-keywords-2018-2018.rs index 6462fc4da60..be632b11374 100644 --- a/src/test/run-pass/edition-keywords-2018-2018.rs +++ b/src/test/run-pass/edition-keywords-2018-2018.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_assignments)] // edition:2018 // aux-build:edition-kw-macro-2018.rs diff --git a/src/test/run-pass/empty-allocation-rvalue-non-null.rs b/src/test/run-pass/empty-allocation-rvalue-non-null.rs index f52a21a997d..28bfb368b6e 100644 --- a/src/test/run-pass/empty-allocation-rvalue-non-null.rs +++ b/src/test/run-pass/empty-allocation-rvalue-non-null.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] // pretty-expanded FIXME #23616 pub fn main() { diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index e92f24a2751..6bb2fe4b34d 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] +#![allow(deprecated)] // ignore-cloudabi no environment variables present // ignore-emscripten env vars don't work? diff --git a/src/test/run-pass/env-null-vars.rs b/src/test/run-pass/env-null-vars.rs index 296764269de..9a461991c1e 100644 --- a/src/test/run-pass/env-null-vars.rs +++ b/src/test/run-pass/env-null-vars.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] + // ignore-windows // ignore-wasm32-bare no libc to test ffi with diff --git a/src/test/run-pass/epoch-gate-feature.rs b/src/test/run-pass/epoch-gate-feature.rs index e3cd1edd209..754e30f3adf 100644 --- a/src/test/run-pass/epoch-gate-feature.rs +++ b/src/test/run-pass/epoch-gate-feature.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_variables)] // Checks if the correct registers are being used to pass arguments // when the sysv64 ABI is specified. diff --git a/src/test/run-pass/estr-uniq.rs b/src/test/run-pass/estr-uniq.rs index 4dfb1541840..e8047b3cb7f 100644 --- a/src/test/run-pass/estr-uniq.rs +++ b/src/test/run-pass/estr-uniq.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_assignments)] +#![allow(unknown_lints)] #![allow(dead_assignment)] diff --git a/src/test/run-pass/existential_type.rs b/src/test/run-pass/existential_type.rs index e63d5c2293a..0193fe4b833 100644 --- a/src/test/run-pass/existential_type.rs +++ b/src/test/run-pass/existential_type.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] #![feature(existential_type)] fn main() { diff --git a/src/test/run-pass/explicit-i-suffix.rs b/src/test/run-pass/explicit-i-suffix.rs index fa3970b6280..b86af5d2fab 100644 --- a/src/test/run-pass/explicit-i-suffix.rs +++ b/src/test/run-pass/explicit-i-suffix.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // pretty-expanded FIXME #23616 pub fn main() { diff --git a/src/test/run-pass/export-glob-imports-target.rs b/src/test/run-pass/export-glob-imports-target.rs index 4f821ebcc18..36724f0b648 100644 --- a/src/test/run-pass/export-glob-imports-target.rs +++ b/src/test/run-pass/export-glob-imports-target.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] +#![allow(dead_code)] // Test that a glob-export functions as an import // when referenced within its own local scope. diff --git a/src/test/run-pass/expr-block.rs b/src/test/run-pass/expr-block.rs index 664555caf26..3459b3c84c5 100644 --- a/src/test/run-pass/expr-block.rs +++ b/src/test/run-pass/expr-block.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] diff --git a/src/test/run-pass/expr-empty-ret.rs b/src/test/run-pass/expr-empty-ret.rs index 02ac2a0b67b..9fb0f07b6a0 100644 --- a/src/test/run-pass/expr-empty-ret.rs +++ b/src/test/run-pass/expr-empty-ret.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Issue #521 // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/exterior.rs b/src/test/run-pass/exterior.rs index 5ab6c7774d5..938c556038f 100644 --- a/src/test/run-pass/exterior.rs +++ b/src/test/run-pass/exterior.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] use std::cell::Cell; diff --git a/src/test/run-pass/fixup-deref-mut.rs b/src/test/run-pass/fixup-deref-mut.rs index 900da3c2d6a..903e97b3158 100644 --- a/src/test/run-pass/fixup-deref-mut.rs +++ b/src/test/run-pass/fixup-deref-mut.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 use std::ops::{Deref, DerefMut}; diff --git a/src/test/run-pass/format-hygiene.rs b/src/test/run-pass/format-hygiene.rs index 6971f775231..892fae417ad 100644 --- a/src/test/run-pass/format-hygiene.rs +++ b/src/test/run-pass/format-hygiene.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] pub const arg0: u8 = 1; pub fn main() { diff --git a/src/test/run-pass/fsu-moves-and-copies.rs b/src/test/run-pass/fsu-moves-and-copies.rs index efd7f66e93b..3be15552dc1 100644 --- a/src/test/run-pass/fsu-moves-and-copies.rs +++ b/src/test/run-pass/fsu-moves-and-copies.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(stable_features)] // Issue 4691: Ensure that functional-struct-updates operates // correctly and moves rather than copy when appropriate. diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index 69a04437691..6e757fb4f9a 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -11,9 +11,8 @@ #![feature(arbitrary_self_types, futures_api, pin)] #![allow(unused)] -use std::pin::PinBox; use std::future::Future; -use std::pin::PinMut; +use std::pin::Pin; use std::rc::Rc; use std::sync::{ Arc, @@ -54,12 +53,12 @@ fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> impl Future for MyFuture { type Output = (); - fn poll(self: PinMut, cx: &mut Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { // Ensure all the methods work appropriately cx.waker().wake(); cx.waker().wake(); cx.local_waker().wake(); - cx.spawner().spawn_obj(PinBox::new(MyFuture).into()).unwrap(); + cx.spawner().spawn_obj(Box::pinned(MyFuture).into()).unwrap(); Poll::Ready(()) } } @@ -72,7 +71,7 @@ fn test_local_waker() { let waker = unsafe { local_waker(counter.clone()) }; let spawner = &mut NoopSpawner; let cx = &mut Context::new(&waker, spawner); - assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx)); + assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(cx)); assert_eq!(1, counter.local_wakes.load(atomic::Ordering::SeqCst)); assert_eq!(2, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst)); } @@ -85,7 +84,7 @@ fn test_local_as_nonlocal_waker() { let waker: LocalWaker = local_waker_from_nonlocal(counter.clone()); let spawner = &mut NoopSpawner; let cx = &mut Context::new(&waker, spawner); - assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx)); + assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(cx)); assert_eq!(0, counter.local_wakes.load(atomic::Ordering::SeqCst)); assert_eq!(3, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst)); } diff --git a/src/test/run-pass/guards-not-exhaustive.rs b/src/test/run-pass/guards-not-exhaustive.rs index 53c3eff5b81..32f262c5a40 100644 --- a/src/test/run-pass/guards-not-exhaustive.rs +++ b/src/test/run-pass/guards-not-exhaustive.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_snake_case)] #[derive(Copy, Clone)] enum Q { R(Option) } diff --git a/src/test/run-pass/guards.rs b/src/test/run-pass/guards.rs index d79dbabac2d..af4e2efb2ba 100644 --- a/src/test/run-pass/guards.rs +++ b/src/test/run-pass/guards.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_shorthand_field_patterns)] #[derive(Copy, Clone)] struct Pair { x: isize, y: isize } diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 2e98e0fe5ca..2b30b5ca9fc 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unused_mut)] // ignore-emscripten No support for threads /** diff --git a/src/test/run-pass/html-literals.rs b/src/test/run-pass/html-literals.rs index 1e1fde4d1e2..1aed2844c96 100644 --- a/src/test/run-pass/html-literals.rs +++ b/src/test/run-pass/html-literals.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] // A test of the macro system. Can we do HTML literals? /* diff --git a/src/test/run-pass/if-ret.rs b/src/test/run-pass/if-ret.rs index 8d475a99b81..5c5c4c80ab1 100644 --- a/src/test/run-pass/if-ret.rs +++ b/src/test/run-pass/if-ret.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_parens)] // pretty-expanded FIXME #23616 fn foo() { if (return) { } } diff --git a/src/test/run-pass/ignore-all-the-things.rs b/src/test/run-pass/ignore-all-the-things.rs index c14f3dc7291..90d858c2858 100644 --- a/src/test/run-pass/ignore-all-the-things.rs +++ b/src/test/run-pass/ignore-all-the-things.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_shorthand_field_patterns)] +#![allow(dead_code)] +#![allow(unused_variables)] // pretty-expanded FIXME #23616 #![feature(slice_patterns)] diff --git a/src/test/run-pass/infer-fn-tail-expr.rs b/src/test/run-pass/infer-fn-tail-expr.rs index f00005fc7d0..a3e0f9dc039 100644 --- a/src/test/run-pass/infer-fn-tail-expr.rs +++ b/src/test/run-pass/infer-fn-tail-expr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // issue #680 diff --git a/src/test/run-pass/init-large-type.rs b/src/test/run-pass/init-large-type.rs index c8f9a0e4cab..0ad0ecf8ce9 100644 --- a/src/test/run-pass/init-large-type.rs +++ b/src/test/run-pass/init-large-type.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // Makes sure that zero-initializing large types is reasonably fast, // Doing it incorrectly causes massive slowdown in LLVM during // optimisation. diff --git a/src/test/run-pass/init-res-into-things.rs b/src/test/run-pass/init-res-into-things.rs index a270b003981..dd838ef98db 100644 --- a/src/test/run-pass/init-res-into-things.rs +++ b/src/test/run-pass/init-res-into-things.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] #![feature(box_syntax)] use std::cell::Cell; diff --git a/src/test/run-pass/instantiable.rs b/src/test/run-pass/instantiable.rs index 28fba70eb24..7d708b475fc 100644 --- a/src/test/run-pass/instantiable.rs +++ b/src/test/run-pass/instantiable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 use std::ptr; diff --git a/src/test/run-pass/invalid_const_promotion.rs b/src/test/run-pass/invalid_const_promotion.rs index a18d82fb7a4..e861f217629 100644 --- a/src/test/run-pass/invalid_const_promotion.rs +++ b/src/test/run-pass/invalid_const_promotion.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] // ignore-wasm32 // ignore-emscripten diff --git a/src/test/run-pass/issue-53728.rs b/src/test/run-pass/issue-53728.rs index f9cb5da29a7..2eaa73ed6f7 100644 --- a/src/test/run-pass/issue-53728.rs +++ b/src/test/run-pass/issue-53728.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #[repr(u16)] enum DeviceKind { Nil = 0, diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index 0fc13319b87..97fa8d36d13 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(unused_attributes)] +#![allow(dead_code)] +#![allow(unknown_lints)] // These are attributes of the implicit crate. Really this just needs to parse // for completeness since .rs files linked from .rc files support this // notation to specify their module's attributes diff --git a/src/test/run-pass/item-name-overload.rs b/src/test/run-pass/item-name-overload.rs index 2827a6df337..b07b0359a2d 100644 --- a/src/test/run-pass/item-name-overload.rs +++ b/src/test/run-pass/item-name-overload.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] diff --git a/src/test/run-pass/keyword-changes-2012-07-31.rs b/src/test/run-pass/keyword-changes-2012-07-31.rs index 9838fe62394..6dbfacf0474 100644 --- a/src/test/run-pass/keyword-changes-2012-07-31.rs +++ b/src/test/run-pass/keyword-changes-2012-07-31.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // return -> return // mod -> module // match -> match diff --git a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs index 1c5d8a69bf3..9788b1e0603 100644 --- a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs +++ b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(dead_code)] use std::thread; fn user(_i: isize) {} diff --git a/src/test/run-pass/lambda-infer-unresolved.rs b/src/test/run-pass/lambda-infer-unresolved.rs index 5109c6fc777..ec12f257f61 100644 --- a/src/test/run-pass/lambda-infer-unresolved.rs +++ b/src/test/run-pass/lambda-infer-unresolved.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] // This should typecheck even though the type of e is not fully // resolved when we finish typechecking the ||. diff --git a/src/test/run-pass/large-records.rs b/src/test/run-pass/large-records.rs index e9c66093fb0..bd685dd4244 100644 --- a/src/test/run-pass/large-records.rs +++ b/src/test/run-pass/large-records.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] diff --git a/src/test/run-pass/last-use-in-block.rs b/src/test/run-pass/last-use-in-block.rs index a2b01f29ae1..bed94de7b95 100644 --- a/src/test/run-pass/last-use-in-block.rs +++ b/src/test/run-pass/last-use-in-block.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_parens)] // Issue #1818 diff --git a/src/test/run-pass/last-use-in-cap-clause.rs b/src/test/run-pass/last-use-in-cap-clause.rs index 5fbcfadf870..d63a712c1aa 100644 --- a/src/test/run-pass/last-use-in-cap-clause.rs +++ b/src/test/run-pass/last-use-in-cap-clause.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Make sure #1399 stays fixed struct A { a: Box } diff --git a/src/test/run-pass/last-use-is-capture.rs b/src/test/run-pass/last-use-is-capture.rs index cb2a2061406..747c7d2eae4 100644 --- a/src/test/run-pass/last-use-is-capture.rs +++ b/src/test/run-pass/last-use-is-capture.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Make sure #1399 stays fixed #![feature(box_syntax)] diff --git a/src/test/run-pass/lazy-init.rs b/src/test/run-pass/lazy-init.rs index d71d7e751a0..a4a3edf71c0 100644 --- a/src/test/run-pass/lazy-init.rs +++ b/src/test/run-pass/lazy-init.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] fn foo(x: isize) { println!("{}", x); } diff --git a/src/test/run-pass/lib-defaults.rs b/src/test/run-pass/lib-defaults.rs index fcaeda9a549..19340ed0e97 100644 --- a/src/test/run-pass/lib-defaults.rs +++ b/src/test/run-pass/lib-defaults.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// dont-check-compiler-stderr (rust-lang/rust#54222) + // ignore-wasm32-bare no libc to test ffi with // compile-flags: -lrust_test_helpers diff --git a/src/test/run-pass/link-section.rs b/src/test/run-pass/link-section.rs index 3336ce7e723..e2369e85d56 100644 --- a/src/test/run-pass/link-section.rs +++ b/src/test/run-pass/link-section.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] #[cfg(not(target_os = "macos"))] #[link_section=".moretext"] fn i_live_in_more_text() -> &'static str { diff --git a/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs b/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs index 6e65cb2afd4..14ef8c1f51f 100644 --- a/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs +++ b/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // +#![allow(dead_code)] #![forbid(non_camel_case_types)] diff --git a/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs b/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs index 3b4bd001e8d..8115a2c50e3 100644 --- a/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs +++ b/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // This is ok because we often use the trailing underscore to mean 'prime' // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/list.rs b/src/test/run-pass/list.rs index 37612415555..bab777d0973 100644 --- a/src/test/run-pass/list.rs +++ b/src/test/run-pass/list.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] // pretty-expanded FIXME #23616 #![feature(box_syntax)] diff --git a/src/test/run-pass/liveness-assign-imm-local-after-ret.rs b/src/test/run-pass/liveness-assign-imm-local-after-ret.rs index 76b44832a8a..bccc939e85e 100644 --- a/src/test/run-pass/liveness-assign-imm-local-after-ret.rs +++ b/src/test/run-pass/liveness-assign-imm-local-after-ret.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unreachable_code)] // pretty-expanded FIXME #23616 #![allow(dead_code)] diff --git a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs index 1991e2b178d..4c501a78b57 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] #[derive(Clone, Debug)] enum foo { a(usize), diff --git a/src/test/run-pass/log-knows-the-names-of-variants.rs b/src/test/run-pass/log-knows-the-names-of-variants.rs index e8852377957..19a7c7105c9 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] #[derive(Debug)] enum foo { a(usize), diff --git a/src/test/run-pass/max-min-classes.rs b/src/test/run-pass/max-min-classes.rs index f0844b8e1eb..f34d5cbd9e3 100644 --- a/src/test/run-pass/max-min-classes.rs +++ b/src/test/run-pass/max-min-classes.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_snake_case)] trait Product { fn product(&self) -> isize; } diff --git a/src/test/run-pass/mid-path-type-params.rs b/src/test/run-pass/mid-path-type-params.rs index 3055f90ee25..7e06530b38c 100644 --- a/src/test/run-pass/mid-path-type-params.rs +++ b/src/test/run-pass/mid-path-type-params.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 struct S { diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs index 211827f9222..6c7c39e5aa5 100644 --- a/src/test/run-pass/monad.rs +++ b/src/test/run-pass/monad.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] diff --git a/src/test/run-pass/monomorphize-abi-alignment.rs b/src/test/run-pass/monomorphize-abi-alignment.rs index 00e97ebc24e..899f3f4ba30 100644 --- a/src/test/run-pass/monomorphize-abi-alignment.rs +++ b/src/test/run-pass/monomorphize-abi-alignment.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] /*! * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment, * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment diff --git a/src/test/run-pass/multiple-reprs.rs b/src/test/run-pass/multiple-reprs.rs index d8eafb806f7..c00fb68f9f7 100644 --- a/src/test/run-pass/multiple-reprs.rs +++ b/src/test/run-pass/multiple-reprs.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] use std::mem::{size_of, align_of}; use std::os::raw::c_int; diff --git a/src/test/run-pass/mutual-recursion-group.rs b/src/test/run-pass/mutual-recursion-group.rs index 72a8847094b..87879e08414 100644 --- a/src/test/run-pass/mutual-recursion-group.rs +++ b/src/test/run-pass/mutual-recursion-group.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/nested-class.rs b/src/test/run-pass/nested-class.rs index 1ad68cb9de0..ca869386856 100644 --- a/src/test/run-pass/nested-class.rs +++ b/src/test/run-pass/nested-class.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] pub fn main() { struct b { diff --git a/src/test/run-pass/never-result.rs b/src/test/run-pass/never-result.rs index 5c0af392f44..a1b9eda8b89 100644 --- a/src/test/run-pass/never-result.rs +++ b/src/test/run-pass/never-result.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] +#![allow(unreachable_code)] // Test that we can extract a ! through pattern matching then use it as several different types. #![feature(never_type)] diff --git a/src/test/run-pass/newlambdas-ret-infer.rs b/src/test/run-pass/newlambdas-ret-infer.rs index 428eed0787a..c2871469de1 100644 --- a/src/test/run-pass/newlambdas-ret-infer.rs +++ b/src/test/run-pass/newlambdas-ret-infer.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Test that the lambda kind is inferred correctly as a return // expression diff --git a/src/test/run-pass/newlambdas-ret-infer2.rs b/src/test/run-pass/newlambdas-ret-infer2.rs index 439ea3f2b57..4d545c7a969 100644 --- a/src/test/run-pass/newlambdas-ret-infer2.rs +++ b/src/test/run-pass/newlambdas-ret-infer2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Test that the lambda kind is inferred correctly as a return // expression diff --git a/src/test/run-pass/newtype-polymorphic.rs b/src/test/run-pass/newtype-polymorphic.rs index e7da8d7bf93..20817cddd05 100644 --- a/src/test/run-pass/newtype-polymorphic.rs +++ b/src/test/run-pass/newtype-polymorphic.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] #[derive(Clone)] diff --git a/src/test/run-pass/newtype.rs b/src/test/run-pass/newtype.rs index 818ea4c9f23..3dbad08f1d8 100644 --- a/src/test/run-pass/newtype.rs +++ b/src/test/run-pass/newtype.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] #[derive(Copy, Clone)] struct mytype(Mytype); diff --git a/src/test/run-pass/nil-decl-in-foreign.rs b/src/test/run-pass/nil-decl-in-foreign.rs index 97ee237771f..96bc80c2125 100644 --- a/src/test/run-pass/nil-decl-in-foreign.rs +++ b/src/test/run-pass/nil-decl-in-foreign.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(improper_ctypes)] +#![allow(dead_code)] // Issue #901 // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/no-core-1.rs b/src/test/run-pass/no-core-1.rs index 7868077fbf2..f5f08969118 100644 --- a/src/test/run-pass/no-core-1.rs +++ b/src/test/run-pass/no-core-1.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] #![feature(no_core, core)] #![no_core] diff --git a/src/test/run-pass/nullable-pointer-size.rs b/src/test/run-pass/nullable-pointer-size.rs index b097d350c8d..bdeae618c8b 100644 --- a/src/test/run-pass/nullable-pointer-size.rs +++ b/src/test/run-pass/nullable-pointer-size.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] use std::mem; diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index c3a1164ba9c..1d66388275e 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] use std::cmp; use std::ops; diff --git a/src/test/run-pass/optimization-fuel-0.stdout b/src/test/run-pass/optimization-fuel-0.stdout new file mode 100644 index 00000000000..3ad405b2b50 --- /dev/null +++ b/src/test/run-pass/optimization-fuel-0.stdout @@ -0,0 +1 @@ +optimization-fuel-exhausted: Reorder fields of "S1" diff --git a/src/test/run-pass/optimization-fuel-1.stdout b/src/test/run-pass/optimization-fuel-1.stdout new file mode 100644 index 00000000000..197e45219c3 --- /dev/null +++ b/src/test/run-pass/optimization-fuel-1.stdout @@ -0,0 +1 @@ +optimization-fuel-exhausted: Reorder fields of "S2" diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs index e22edb3caed..32faab4c12c 100644 --- a/src/test/run-pass/option-unwrap.rs +++ b/src/test/run-pass/option-unwrap.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] use std::cell::Cell; struct dtor<'a> { diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index 6ed07fb2f7d..cd0f7cdbf6d 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(unconditional_recursion)] // ignore-android: FIXME (#20004) // ignore-musl // ignore-cloudabi no processes diff --git a/src/test/run-pass/output-slot-variants.rs b/src/test/run-pass/output-slot-variants.rs index 2171b8c481d..e4013854e78 100644 --- a/src/test/run-pass/output-slot-variants.rs +++ b/src/test/run-pass/output-slot-variants.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unknown_lints)] // pretty-expanded FIXME #23616 #![allow(dead_assignment)] diff --git a/src/test/run-pass/over-constrained-vregs.rs b/src/test/run-pass/over-constrained-vregs.rs index e4e07941470..edbb311fcda 100644 --- a/src/test/run-pass/over-constrained-vregs.rs +++ b/src/test/run-pass/over-constrained-vregs.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // Regression test for issue #152. pub fn main() { let mut b: usize = 1_usize; diff --git a/src/test/run-pass/parse-panic.rs b/src/test/run-pass/parse-panic.rs index 22b24ebb3b5..5c904295bb4 100644 --- a/src/test/run-pass/parse-panic.rs +++ b/src/test/run-pass/parse-panic.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #![allow(unreachable_code)] fn dont_call_me() { panic!(); println!("{}", 1); } diff --git a/src/test/run-pass/paths-containing-nul.rs b/src/test/run-pass/paths-containing-nul.rs index e0fe1ea72df..3359f1064c9 100644 --- a/src/test/run-pass/paths-containing-nul.rs +++ b/src/test/run-pass/paths-containing-nul.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] // ignore-cloudabi no files or I/O // ignore-wasm32-bare no files or I/O diff --git a/src/test/run-pass/project-cache-issue-37154.rs b/src/test/run-pass/project-cache-issue-37154.rs index 29dc6984e23..24fb400150a 100644 --- a/src/test/run-pass/project-cache-issue-37154.rs +++ b/src/test/run-pass/project-cache-issue-37154.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Regression test for #37154: the problem here was that the cache // results in a false error because it was caching skolemized results // even after those skolemized regions had been popped. diff --git a/src/test/run-pass/project-defer-unification.rs b/src/test/run-pass/project-defer-unification.rs index 9a6ea2272fe..c4a3856bcbc 100644 --- a/src/test/run-pass/project-defer-unification.rs +++ b/src/test/run-pass/project-defer-unification.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unreachable_code)] // A regression test extracted from image-0.3.11. The point of // failure was in `index_colors` below. @@ -92,6 +95,10 @@ pub fn index_colors(image: &ImageBuffer>) -> ImageBuffer, Vec> where Pix: Pixel + 'static, { + // When NLL-enabled, `let mut` below is deemed unnecessary (due to + // the remaining code being unreachable); so ignore that lint. + #![allow(unused_mut)] + let mut indices: ImageBuffer<_,Vec<_>> = loop { }; for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) { // failured occurred here ^^ because we were requiring that we diff --git a/src/test/run-pass/ptr-coercion.rs b/src/test/run-pass/ptr-coercion.rs index ac1b6aebec5..3a4d2b3e602 100644 --- a/src/test/run-pass/ptr-coercion.rs +++ b/src/test/run-pass/ptr-coercion.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] // Test coercions between pointers which don't do anything fancy like unsizing. // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/pure-sum.rs b/src/test/run-pass/pure-sum.rs index 3313196a5ec..5f6b9b17e36 100644 --- a/src/test/run-pass/pure-sum.rs +++ b/src/test/run-pass/pure-sum.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Check that functions can modify local state. // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/range-type-infer.rs b/src/test/run-pass/range-type-infer.rs index b6d4d09d697..809c1ba702b 100644 --- a/src/test/run-pass/range-type-infer.rs +++ b/src/test/run-pass/range-type-infer.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // Make sure the type inference for the new range expression work as // good as the old one. Check out issue #21672, #21595 and #21649 for // more details. diff --git a/src/test/run-pass/range.rs b/src/test/run-pass/range.rs index 4c249bbe1f7..2fae4d3cf26 100644 --- a/src/test/run-pass/range.rs +++ b/src/test/run-pass/range.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_comparisons)] +#![allow(dead_code)] +#![allow(unused_mut)] // Test range syntax. diff --git a/src/test/run-pass/range_inclusive_gate.rs b/src/test/run-pass/range_inclusive_gate.rs index 6c2731fa5a9..09132efe18c 100644 --- a/src/test/run-pass/range_inclusive_gate.rs +++ b/src/test/run-pass/range_inclusive_gate.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_comparisons)] // Test that you only need the syntax gate if you don't mention the structs. // (Obsoleted since both features are stabilized) diff --git a/src/test/run-pass/rcvr-borrowed-to-region.rs b/src/test/run-pass/rcvr-borrowed-to-region.rs index bc869113fe9..02392be7e4f 100644 --- a/src/test/run-pass/rcvr-borrowed-to-region.rs +++ b/src/test/run-pass/rcvr-borrowed-to-region.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] #![feature(box_syntax)] trait get { diff --git a/src/test/run-pass/readalias.rs b/src/test/run-pass/readalias.rs index 56b15c24361..d7ddd9505d7 100644 --- a/src/test/run-pass/readalias.rs +++ b/src/test/run-pass/readalias.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] diff --git a/src/test/run-pass/resolve-issue-2428.rs b/src/test/run-pass/resolve-issue-2428.rs index 6159b24165e..0ad97e78d1a 100644 --- a/src/test/run-pass/resolve-issue-2428.rs +++ b/src/test/run-pass/resolve-issue-2428.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] const foo: isize = 4 >> 1; enum bs { thing = foo } diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs index 4d0c2900a0f..ccc3396e50c 100644 --- a/src/test/run-pass/resource-assign-is-not-copy.rs +++ b/src/test/run-pass/resource-assign-is-not-copy.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] use std::cell::Cell; #[derive(Debug)] diff --git a/src/test/run-pass/resource-destruct.rs b/src/test/run-pass/resource-destruct.rs index c92a9ca8480..d3ba221b34a 100644 --- a/src/test/run-pass/resource-destruct.rs +++ b/src/test/run-pass/resource-destruct.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] use std::cell::Cell; struct shrinky_pointer<'a> { diff --git a/src/test/run-pass/ret-none.rs b/src/test/run-pass/ret-none.rs index 032a4b662cb..72ee3dbfe2d 100644 --- a/src/test/run-pass/ret-none.rs +++ b/src/test/run-pass/ret-none.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/rustc-rust-log.rs b/src/test/run-pass/rustc-rust-log.rs index 629387d4cb1..8c3e4b391e9 100644 --- a/src/test/run-pass/rustc-rust-log.rs +++ b/src/test/run-pass/rustc-rust-log.rs @@ -8,6 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// This test is just checking that we won't ICE if logging is turned +// on; don't bother trying to compare that (copious) output. (Note +// also that this test potentially silly, since we do not build+test +// debug versions of rustc as part of our continuous integration +// process...) +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr + // rustc-env:RUST_LOG=debug fn main() {} diff --git a/src/test/run-pass/segfault-no-out-of-stack.rs b/src/test/run-pass/segfault-no-out-of-stack.rs index 307ead4b74f..a85fe6733dd 100644 --- a/src/test/run-pass/segfault-no-out-of-stack.rs +++ b/src/test/run-pass/segfault-no-out-of-stack.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // ignore-cloudabi can't run commands // ignore-emscripten can't run commands diff --git a/src/test/run-pass/semistatement-in-lambda.rs b/src/test/run-pass/semistatement-in-lambda.rs index 0fc5fe498a6..c9ab466e445 100644 --- a/src/test/run-pass/semistatement-in-lambda.rs +++ b/src/test/run-pass/semistatement-in-lambda.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] pub fn main() { // Test that lambdas behave as unary expressions with block-like expressions diff --git a/src/test/run-pass/shadow.rs b/src/test/run-pass/shadow.rs index b764fc6f1ec..b2028927da4 100644 --- a/src/test/run-pass/shadow.rs +++ b/src/test/run-pass/shadow.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] fn foo(c: Vec ) { let a: isize = 5; let mut b: Vec = Vec::new(); diff --git a/src/test/run-pass/shadowed-use-visibility.rs b/src/test/run-pass/shadowed-use-visibility.rs index d2a32da4fea..b54ba3d2ce7 100644 --- a/src/test/run-pass/shadowed-use-visibility.rs +++ b/src/test/run-pass/shadowed-use-visibility.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] mod foo { pub fn f() {} diff --git a/src/test/run-pass/sigpipe-should-be-ignored.rs b/src/test/run-pass/sigpipe-should-be-ignored.rs index f5e2239538f..c964bcb94ef 100644 --- a/src/test/run-pass/sigpipe-should-be-ignored.rs +++ b/src/test/run-pass/sigpipe-should-be-ignored.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] // Be sure that when a SIGPIPE would have been received that the entire process // doesn't die in a ball of fire, but rather it's gracefully handled. diff --git a/src/test/run-pass/simple-infer.rs b/src/test/run-pass/simple-infer.rs index 04c1af4326b..6feb2da5fac 100644 --- a/src/test/run-pass/simple-infer.rs +++ b/src/test/run-pass/simple-infer.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_mut)] pub fn main() { let mut n; n = 1; println!("{}", n); } diff --git a/src/test/run-pass/simple_global_asm.rs b/src/test/run-pass/simple_global_asm.rs index cd8273c6bc2..2d8ac6d99f7 100644 --- a/src/test/run-pass/simple_global_asm.rs +++ b/src/test/run-pass/simple_global_asm.rs @@ -10,6 +10,7 @@ #![feature(global_asm)] #![feature(naked_functions)] +#![allow(dead_code)] #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] global_asm!(r#" diff --git a/src/test/run-pass/size-and-align.rs b/src/test/run-pass/size-and-align.rs index 13d55e0172e..0da63f93cc6 100644 --- a/src/test/run-pass/size-and-align.rs +++ b/src/test/run-pass/size-and-align.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] enum clam { a(T, isize), b, } fn uhoh(v: Vec> ) { diff --git a/src/test/run-pass/sized-borrowed-pointer.rs b/src/test/run-pass/sized-borrowed-pointer.rs index 76c06d560d7..03425e04725 100644 --- a/src/test/run-pass/sized-borrowed-pointer.rs +++ b/src/test/run-pass/sized-borrowed-pointer.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Possibly-dynamic size of typaram should be cleared at pointer boundary. // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/sized-owned-pointer.rs b/src/test/run-pass/sized-owned-pointer.rs index d3a6b104dba..5624910cee9 100644 --- a/src/test/run-pass/sized-owned-pointer.rs +++ b/src/test/run-pass/sized-owned-pointer.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Possibly-dynamic size of typaram should be cleared at pointer boundary. diff --git a/src/test/run-pass/snake-case-no-lowercase-equivalent.rs b/src/test/run-pass/snake-case-no-lowercase-equivalent.rs index 90ea7537c6e..49fb4176755 100644 --- a/src/test/run-pass/snake-case-no-lowercase-equivalent.rs +++ b/src/test/run-pass/snake-case-no-lowercase-equivalent.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 #![feature(non_ascii_idents)] diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs index b1d7e5435c4..041286fe656 100644 --- a/src/test/run-pass/sse2.rs +++ b/src/test/run-pass/sse2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // min-llvm-version 6.0 // ^ needs MCSubtargetInfo::checkFeatures() // ignore-cloudabi no std::env diff --git a/src/test/run-pass/structured-compare.rs b/src/test/run-pass/structured-compare.rs index 7974366c395..22d1eeb0e0a 100644 --- a/src/test/run-pass/structured-compare.rs +++ b/src/test/run-pass/structured-compare.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] diff --git a/src/test/run-pass/super-fast-paren-parsing.rs b/src/test/run-pass/super-fast-paren-parsing.rs index a1bbd190211..5e120bd80ee 100644 --- a/src/test/run-pass/super-fast-paren-parsing.rs +++ b/src/test/run-pass/super-fast-paren-parsing.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] +#![allow(dead_code)] // exec-env:RUST_MIN_STACK=16000000 // rustc-env:RUST_MIN_STACK=16000000 // diff --git a/src/test/run-pass/super.rs b/src/test/run-pass/super.rs index 51520c77751..5958565823f 100644 --- a/src/test/run-pass/super.rs +++ b/src/test/run-pass/super.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 pub mod a { diff --git a/src/test/run-pass/swap-overlapping.rs b/src/test/run-pass/swap-overlapping.rs index 2e5386d6866..8fcbfce0f7a 100644 --- a/src/test/run-pass/swap-overlapping.rs +++ b/src/test/run-pass/swap-overlapping.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/trivial-message.rs b/src/test/run-pass/trivial-message.rs index fd60c614638..c6445190c0a 100644 --- a/src/test/run-pass/trivial-message.rs +++ b/src/test/run-pass/trivial-message.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] /* This is about the simplest program that can successfully send a message. diff --git a/src/test/run-pass/try-block.rs b/src/test/run-pass/try-block.rs index a7e7cc20620..f618d16c598 100644 --- a/src/test/run-pass/try-block.rs +++ b/src/test/run-pass/try-block.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // compile-flags: --edition 2018 #![feature(try_blocks)] diff --git a/src/test/run-pass/try-is-identifier-edition2015.rs b/src/test/run-pass/try-is-identifier-edition2015.rs index aafb52e4c49..94e2d579993 100644 --- a/src/test/run-pass/try-is-identifier-edition2015.rs +++ b/src/test/run-pass/try-is-identifier-edition2015.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] // compile-flags: --edition 2015 fn main() { diff --git a/src/test/run-pass/try-operator-hygiene.rs b/src/test/run-pass/try-operator-hygiene.rs index 53d6185020a..045a8a50320 100644 --- a/src/test/run-pass/try-operator-hygiene.rs +++ b/src/test/run-pass/try-operator-hygiene.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] +#![allow(dead_code)] // `expr?` expands to: // // match expr { diff --git a/src/test/run-pass/try-operator.rs b/src/test/run-pass/try-operator.rs index d615c5f1034..f212e560bf2 100644 --- a/src/test/run-pass/try-operator.rs +++ b/src/test/run-pass/try-operator.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // ignore-cloudabi no std::fs use std::fs::File; diff --git a/src/test/run-pass/try-wait.rs b/src/test/run-pass/try-wait.rs index b8c0d80c5a6..7c2333ffdaa 100644 --- a/src/test/run-pass/try-wait.rs +++ b/src/test/run-pass/try-wait.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // ignore-cloudabi no processes // ignore-emscripten no processes diff --git a/src/test/run-pass/tup.rs b/src/test/run-pass/tup.rs index 86ca37deb02..b6fb2119308 100644 --- a/src/test/run-pass/tup.rs +++ b/src/test/run-pass/tup.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] type point = (isize, isize); diff --git a/src/test/run-pass/tydesc-name.rs b/src/test/run-pass/tydesc-name.rs index 4a169c0a384..a66830e23df 100644 --- a/src/test/run-pass/tydesc-name.rs +++ b/src/test/run-pass/tydesc-name.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] #![feature(core_intrinsics)] diff --git a/src/test/run-pass/type-ascription.rs b/src/test/run-pass/type-ascription.rs index 18fb8e2e408..b5eb2fe1705 100644 --- a/src/test/run-pass/type-ascription.rs +++ b/src/test/run-pass/type-ascription.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_variables)] // Type ascription doesn't lead to unsoundness #![feature(type_ascription)] diff --git a/src/test/run-pass/type-in-nested-module.rs b/src/test/run-pass/type-in-nested-module.rs index 7e2360caa93..8fef294c0cf 100644 --- a/src/test/run-pass/type-in-nested-module.rs +++ b/src/test/run-pass/type-in-nested-module.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/type-infer-generalize-ty-var.rs b/src/test/run-pass/type-infer-generalize-ty-var.rs index d7fb85ca484..b918c3fc396 100644 --- a/src/test/run-pass/type-infer-generalize-ty-var.rs +++ b/src/test/run-pass/type-infer-generalize-ty-var.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] // Test a scenario where we generate a constraint like `?1 <: &?2`. // In such a case, it is important that we instantiate `?1` with `&?3` // where `?3 <: ?2`, and not with `&?2`. This is a regression test for diff --git a/src/test/run-pass/type-param-constraints.rs b/src/test/run-pass/type-param-constraints.rs index 1a3bdcca7a1..e05f6f153a4 100644 --- a/src/test/run-pass/type-param-constraints.rs +++ b/src/test/run-pass/type-param-constraints.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 #![feature(box_syntax)] diff --git a/src/test/run-pass/type-param.rs b/src/test/run-pass/type-param.rs index c59e40934fb..246cf209efb 100644 --- a/src/test/run-pass/type-param.rs +++ b/src/test/run-pass/type-param.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/type-params-in-for-each.rs b/src/test/run-pass/type-params-in-for-each.rs index fea2bd978eb..76ac2d14b93 100644 --- a/src/test/run-pass/type-params-in-for-each.rs +++ b/src/test/run-pass/type-params-in-for-each.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/type-ptr.rs b/src/test/run-pass/type-ptr.rs index 67ead80c89b..94d46b1a96e 100644 --- a/src/test/run-pass/type-ptr.rs +++ b/src/test/run-pass/type-ptr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // pretty-expanded FIXME #23616 fn f(a: *const isize) -> *const isize { return a; } diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index 5eb079988f5..26cadf16e29 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] #![feature(never_type)] use std::mem::size_of; diff --git a/src/test/run-pass/typeck_type_placeholder_1.rs b/src/test/run-pass/typeck_type_placeholder_1.rs index 113d52ffb35..ee482ea3c52 100644 --- a/src/test/run-pass/typeck_type_placeholder_1.rs +++ b/src/test/run-pass/typeck_type_placeholder_1.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // This test checks that the `_` type placeholder works // correctly for enabling type inference. diff --git a/src/test/run-pass/typeclasses-eq-example-static.rs b/src/test/run-pass/typeclasses-eq-example-static.rs index d386f27d8c2..fecc6d70509 100644 --- a/src/test/run-pass/typeclasses-eq-example-static.rs +++ b/src/test/run-pass/typeclasses-eq-example-static.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] #![feature(box_syntax)] // Example from lkuper's intern talk, August 2012 -- now with static diff --git a/src/test/run-pass/typeclasses-eq-example.rs b/src/test/run-pass/typeclasses-eq-example.rs index 8e8fd9bf648..f2b6e9cd255 100644 --- a/src/test/run-pass/typeclasses-eq-example.rs +++ b/src/test/run-pass/typeclasses-eq-example.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] #![feature(box_syntax)] // Example from lkuper's intern talk, August 2012. diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs index 54d5415a553..2dbe2c0a402 100644 --- a/src/test/run-pass/typeid-intrinsic.rs +++ b/src/test/run-pass/typeid-intrinsic.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] // aux-build:typeid-intrinsic-aux1.rs // aux-build:typeid-intrinsic-aux2.rs diff --git a/src/test/run-pass/typestate-cfg-nesting.rs b/src/test/run-pass/typestate-cfg-nesting.rs index 2acaff26269..a1047d47b4b 100644 --- a/src/test/run-pass/typestate-cfg-nesting.rs +++ b/src/test/run-pass/typestate-cfg-nesting.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unknown_lints)] // pretty-expanded FIXME #23616 #![allow(dead_assignment)] diff --git a/src/test/run-pass/underscore-lifetimes.rs b/src/test/run-pass/underscore-lifetimes.rs index 4dd1a565c9f..0f601021f6a 100644 --- a/src/test/run-pass/underscore-lifetimes.rs +++ b/src/test/run-pass/underscore-lifetimes.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] struct Foo<'a>(&'a u8); fn foo(x: &u8) -> Foo<'_> { diff --git a/src/test/run-pass/unit.rs b/src/test/run-pass/unit.rs index 67eceba020c..17ed465f995 100644 --- a/src/test/run-pass/unit.rs +++ b/src/test/run-pass/unit.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_assignments)] +#![allow(unknown_lints)] // pretty-expanded FIXME #23616 #![allow(unused_variables)] diff --git a/src/test/run-pass/unreachable-code-1.rs b/src/test/run-pass/unreachable-code-1.rs index 6448056fb11..4e257069506 100644 --- a/src/test/run-pass/unreachable-code-1.rs +++ b/src/test/run-pass/unreachable-code-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(unreachable_code)] #![allow(unused_variables)] #![allow(dead_code)] diff --git a/src/test/run-pass/unreachable-code.rs b/src/test/run-pass/unreachable-code.rs index 5cb5e8c4f99..4fffe98e4b2 100644 --- a/src/test/run-pass/unreachable-code.rs +++ b/src/test/run-pass/unreachable-code.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(dead_code)] #![allow(path_statements)] #![allow(unreachable_code)] diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs index f3a2ad749a1..ac5a0db1cd2 100644 --- a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // // See also: compile-fail/unsafe-fn-called-from-safe.rs diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs index 37c72ba8ab0..a40a764bfc2 100644 --- a/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // // See also: compile-fail/unsafe-fn-called-from-safe.rs diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index 26f7b767988..6a58c9aa90b 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(type_alias_bounds)] +#![allow(dead_code)] // Test syntax checks for `?Sized` syntax. use std::marker::PhantomData; diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs index 90b99f98533..e4480d7e97a 100644 --- a/src/test/run-pass/unsized2.rs +++ b/src/test/run-pass/unsized2.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unconditional_recursion)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] #![feature(box_syntax)] // Test sized-ness checking in substitution. diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs index 85ee21e0902..e0ddc854fa0 100644 --- a/src/test/run-pass/unwind-resource.rs +++ b/src/test/run-pass/unwind-resource.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] // ignore-emscripten no threads support use std::sync::mpsc::{channel, Sender}; diff --git a/src/test/run-pass/use-keyword-2.rs b/src/test/run-pass/use-keyword-2.rs index 60016f59594..c669b522ab2 100644 --- a/src/test/run-pass/use-keyword-2.rs +++ b/src/test/run-pass/use-keyword-2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] pub struct A; mod test { diff --git a/src/test/run-pass/use-mod.rs b/src/test/run-pass/use-mod.rs index 49ad171eaa2..3115a359ff1 100644 --- a/src/test/run-pass/use-mod.rs +++ b/src/test/run-pass/use-mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_imports)] // pretty-expanded FIXME #23616 pub use foo::bar::{self, First}; diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 09a3849b915..d6899e79152 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] // pretty-expanded FIXME #23616 #![allow(unused_imports)] diff --git a/src/test/run-pass/utf8_idents.rs b/src/test/run-pass/utf8_idents.rs index 579070a295a..4614e47609a 100644 --- a/src/test/run-pass/utf8_idents.rs +++ b/src/test/run-pass/utf8_idents.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // +#![allow(non_snake_case)] #![feature(non_ascii_idents)] diff --git a/src/test/run-pass/variant-attributes.rs b/src/test/run-pass/variant-attributes.rs index 18987d1e016..0c92778cec4 100644 --- a/src/test/run-pass/variant-attributes.rs +++ b/src/test/run-pass/variant-attributes.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attributes)] +#![allow(non_camel_case_types)] +#![allow(dead_code)] // pp-exact - Make sure we actually print the attributes // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/volatile-fat-ptr.rs b/src/test/run-pass/volatile-fat-ptr.rs index 03ba5587fce..799917c4b05 100644 --- a/src/test/run-pass/volatile-fat-ptr.rs +++ b/src/test/run-pass/volatile-fat-ptr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(stable_features)] #![feature(volatile)] use std::ptr::{read_volatile, write_volatile}; diff --git a/src/test/run-pass/warn-ctypes-inhibit.rs b/src/test/run-pass/warn-ctypes-inhibit.rs index 81a3c94eec3..0c059cb607e 100644 --- a/src/test/run-pass/warn-ctypes-inhibit.rs +++ b/src/test/run-pass/warn-ctypes-inhibit.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // compile-flags:-D improper-ctypes // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs index 35120e428a7..c688ec540da 100644 --- a/src/test/run-pass/weird-exprs.rs +++ b/src/test/run-pass/weird-exprs.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unreachable_code)] +#![allow(unused_parens)] // compile-flags: -Z borrowck=compare #![recursion_limit = "128"] diff --git a/src/test/run-pass/wf-bound-region-in-object-type.rs b/src/test/run-pass/wf-bound-region-in-object-type.rs index cdb5e3fe1d4..b71f633bef4 100644 --- a/src/test/run-pass/wf-bound-region-in-object-type.rs +++ b/src/test/run-pass/wf-bound-region-in-object-type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unused_variables)] // Test that the `wf` checker properly handles bound regions in object // types. Compiling this code used to trigger an ICE. diff --git a/src/test/run-pass/writealias.rs b/src/test/run-pass/writealias.rs index 7339fe47dc2..d190e91575e 100644 --- a/src/test/run-pass/writealias.rs +++ b/src/test/run-pass/writealias.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] use std::sync::Mutex; diff --git a/src/test/run-pass/wrong-hashset-issue-42918.rs b/src/test/run-pass/wrong-hashset-issue-42918.rs index 5a23adeceb5..0fcd3efd9ce 100644 --- a/src/test/run-pass/wrong-hashset-issue-42918.rs +++ b/src/test/run-pass/wrong-hashset-issue-42918.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // +#![allow(dead_code)] // compile-flags: -O use std::collections::HashSet; diff --git a/src/test/run-pass/x86stdcall2.rs b/src/test/run-pass/x86stdcall2.rs index bbdd65f7e5b..8ea7ec67f1b 100644 --- a/src/test/run-pass/x86stdcall2.rs +++ b/src/test/run-pass/x86stdcall2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(non_camel_case_types)] pub type HANDLE = usize; pub type DWORD = u32; pub type SIZE_T = u32; diff --git a/src/test/run-pass/yield.rs b/src/test/run-pass/yield.rs index db884638622..9910c534926 100644 --- a/src/test/run-pass/yield.rs +++ b/src/test/run-pass/yield.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(unused_mut)] // ignore-emscripten no threads support use std::thread; diff --git a/src/test/run-pass/yield1.rs b/src/test/run-pass/yield1.rs index cab68794e1c..0b603452339 100644 --- a/src/test/run-pass/yield1.rs +++ b/src/test/run-pass/yield1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_must_use)] +#![allow(unused_mut)] // ignore-emscripten no threads support use std::thread; diff --git a/src/test/rustdoc-js/pinbox-new.js b/src/test/rustdoc-js/pinbox-new.js deleted file mode 100644 index 55842dc8e45..00000000000 --- a/src/test/rustdoc-js/pinbox-new.js +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exact-check - -const QUERY = 'pinbox::new'; - -const EXPECTED = { - 'others': [ - { 'path': 'std::pin::PinBox', 'name': 'new' }, - { 'path': 'alloc::pin::PinBox', 'name': 'new' }, - ], -}; diff --git a/src/test/rustdoc-js/vec-new.js b/src/test/rustdoc-js/vec-new.js index 4a654ccb135..42951724648 100644 --- a/src/test/rustdoc-js/vec-new.js +++ b/src/test/rustdoc-js/vec-new.js @@ -14,6 +14,5 @@ const EXPECTED = { 'others': [ { 'path': 'std::vec::Vec', 'name': 'new' }, { 'path': 'std::vec::Vec', 'name': 'ne' }, - { 'path': 'std::pin::PinBox', 'name': 'new' }, ], }; diff --git a/src/test/rustdoc/doc-proc-macro.rs b/src/test/rustdoc/doc-proc-macro.rs index b3b403a7b86..01a4a410b03 100644 --- a/src/test/rustdoc/doc-proc-macro.rs +++ b/src/test/rustdoc/doc-proc-macro.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-stage1 + // Issue #52129: ICE when trying to document the `quote` proc-macro from proc_macro // As of this writing, we don't currently attempt to document proc-macros. However, we shouldn't diff --git a/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs new file mode 100644 index 00000000000..7457a5d4899 --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "inner"] + +pub struct SomeStruct; + +fn asdf() { + const _FOO: () = { + impl Clone for SomeStruct { + fn clone(&self) -> Self { + SomeStruct + } + } + }; +} diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs new file mode 100644 index 00000000000..5b5410b1da4 --- /dev/null +++ b/src/test/rustdoc/inline_cross/trait-vis.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:trait-vis.rs + +extern crate inner; + +// @has trait_vis/struct.SomeStruct.html +// @has - '//code' 'impl Clone for SomeStruct' +pub use inner::SomeStruct; diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs new file mode 100644 index 00000000000..73b1cc2ce8f --- /dev/null +++ b/src/test/rustdoc/inline_local/trait-vis.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait ThisTrait {} + +mod asdf { + use ThisTrait; + + pub struct SomeStruct; + + impl ThisTrait for SomeStruct {} + + trait PrivateTrait {} + + impl PrivateTrait for SomeStruct {} +} + +// @has trait_vis/struct.SomeStruct.html +// @has - '//code' 'impl ThisTrait for SomeStruct' +// !@has - '//code' 'impl PrivateTrait for SomeStruct' +pub use asdf::SomeStruct; diff --git a/src/test/rustdoc/intra-link-in-bodies.rs b/src/test/rustdoc/intra-link-in-bodies.rs new file mode 100644 index 00000000000..8c01941234e --- /dev/null +++ b/src/test/rustdoc/intra-link-in-bodies.rs @@ -0,0 +1,40 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// we need to make sure that intra-doc links on trait impls get resolved in the right scope + +#![deny(intra_doc_link_resolution_failure)] + +pub mod inner { + pub struct SomethingOutOfScope; +} + +pub mod other { + use inner::SomethingOutOfScope; + use SomeTrait; + + pub struct OtherStruct; + + /// Let's link to [SomethingOutOfScope] while we're at it. + impl SomeTrait for OtherStruct {} +} + +pub trait SomeTrait {} + +pub struct SomeStruct; + +fn __implementation_details() { + use inner::SomethingOutOfScope; + + // FIXME: intra-links resolve in their nearest module scope, not their actual scope in cases + // like this + // Let's link to [SomethingOutOfScope] while we're at it. + impl SomeTrait for SomeStruct {} +} diff --git a/src/test/rustdoc/issue-53812.rs b/src/test/rustdoc/issue-53812.rs new file mode 100644 index 00000000000..60d19fbcd1a --- /dev/null +++ b/src/test/rustdoc/issue-53812.rs @@ -0,0 +1,30 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait MyIterator { +} + +pub struct MyStruct(T); + +macro_rules! array_impls { + ($($N:expr)+) => { + $( + impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> { + } + )+ + } +} + +// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]//h3[1]' 'MyStruct<[T; 0]>' +// @has - '//*[@id="implementors-list"]//h3[2]' 'MyStruct<[T; 1]>' +// @has - '//*[@id="implementors-list"]//h3[3]' 'MyStruct<[T; 2]>' +// @has - '//*[@id="implementors-list"]//h3[4]' 'MyStruct<[T; 3]>' +// @has - '//*[@id="implementors-list"]//h3[5]' 'MyStruct<[T; 10]>' +array_impls! { 10 3 2 1 0 } diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs index b255ffddafa..73a026c581b 100644 --- a/src/test/rustdoc/keyword.rs +++ b/src/test/rustdoc/keyword.rs @@ -15,6 +15,7 @@ // @has foo/index.html '//h2[@id="keywords"]' 'Keywords' // @has foo/index.html '//a[@href="keyword.match.html"]' 'match' // @has foo/keyword.match.html '//a[@class="keyword"]' 'match' +// @has foo/keyword.match.html '//span[@class="in-band"]' 'Keyword match' // @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!' // @!has foo/index.html '//a/@href' 'foo/index.html' // @!has foo/foo/index.html diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs index b4351b8268c..a771b1b15ce 100644 --- a/src/test/rustdoc/primitive-generic-impl.rs +++ b/src/test/rustdoc/primitive-generic-impl.rs @@ -10,9 +10,6 @@ #![crate_name = "foo"] -// we need to reexport something from libstd so that `all_trait_implementations` is called. -pub use std::string::String; - include!("primitive/primitive-generic-impl.rs"); // @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl ToString for T' diff --git a/src/test/rustdoc/traits-in-bodies-private.rs b/src/test/rustdoc/traits-in-bodies-private.rs new file mode 100644 index 00000000000..ac3be7e61e9 --- /dev/null +++ b/src/test/rustdoc/traits-in-bodies-private.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// when implementing the fix for traits-in-bodies, there was an ICE when documenting private items +// and a trait was defined in non-module scope + +// compile-flags:--document-private-items + +// @has traits_in_bodies_private/struct.SomeStruct.html +// @!has - '//code' 'impl HiddenTrait for SomeStruct' +pub struct SomeStruct; + +fn __implementation_details() { + trait HiddenTrait {} + impl HiddenTrait for SomeStruct {} +} diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs index 3acf4af5fd2..a1d4019bba2 100644 --- a/src/test/rustdoc/traits-in-bodies.rs +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -11,11 +11,10 @@ //prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it //didn't see that `SomeStruct` implemented `Clone` -//FIXME(misdreavus): whenever rustdoc shows traits impl'd inside bodies, make sure this test -//reflects that - pub struct Bounded(T); +// @has traits_in_bodies/struct.SomeStruct.html +// @has - '//code' 'impl Clone for SomeStruct' pub struct SomeStruct; fn asdf() -> Bounded { @@ -27,3 +26,37 @@ fn clone(&self) -> SomeStruct { Bounded(SomeStruct) } + +// @has traits_in_bodies/struct.Point.html +// @has - '//code' 'impl Copy for Point' +#[derive(Clone)] +pub struct Point { + x: i32, + y: i32, +} + +const _FOO: () = { + impl Copy for Point {} + () +}; + +// @has traits_in_bodies/struct.Inception.html +// @has - '//code' 'impl Clone for Inception' +pub struct Inception; + +static _BAR: usize = { + trait HiddenTrait { + fn hidden_fn(&self) { + for _ in 0..5 { + impl Clone for Inception { + fn clone(&self) -> Self { + // we need to go deeper + Inception + } + } + } + } + } + + 5 +}; diff --git a/src/test/ui-fulldeps/attribute-order-restricted.rs b/src/test/ui-fulldeps/attribute-order-restricted.rs new file mode 100644 index 00000000000..553cd86e620 --- /dev/null +++ b/src/test/ui-fulldeps/attribute-order-restricted.rs @@ -0,0 +1,32 @@ +// aux-build:attr_proc_macro.rs +// compile-flags:--test + +#![feature(test)] + +extern crate test; +extern crate attr_proc_macro; +use attr_proc_macro::*; + +#[attr_proc_macro] // OK +#[derive(Clone)] +struct Before; + +#[derive(Clone)] +#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]` +struct After; + +#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` +#[test] +fn test_before() {} + +#[test] +#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` +fn test_after() {} + +#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` +#[bench] +fn bench_before(b: &mut test::Bencher) {} + +#[bench] +#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` +fn bench_after(b: &mut test::Bencher) {} diff --git a/src/test/ui-fulldeps/attribute-order-restricted.stderr b/src/test/ui-fulldeps/attribute-order-restricted.stderr new file mode 100644 index 00000000000..841fc630b22 --- /dev/null +++ b/src/test/ui-fulldeps/attribute-order-restricted.stderr @@ -0,0 +1,32 @@ +error: macro attributes must be placed before `#[derive]` + --> $DIR/attribute-order-restricted.rs:15:1 + | +LL | #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]` + | ^^^^^^^^^^^^^^^^^^ + +error: macro attributes cannot be used together with `#[test]` or `#[bench]` + --> $DIR/attribute-order-restricted.rs:18:1 + | +LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` + | ^^^^^^^^^^^^^^^^^^ + +error: macro attributes cannot be used together with `#[test]` or `#[bench]` + --> $DIR/attribute-order-restricted.rs:23:1 + | +LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` + | ^^^^^^^^^^^^^^^^^^ + +error: macro attributes cannot be used together with `#[test]` or `#[bench]` + --> $DIR/attribute-order-restricted.rs:26:1 + | +LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` + | ^^^^^^^^^^^^^^^^^^ + +error: macro attributes cannot be used together with `#[test]` or `#[bench]` + --> $DIR/attribute-order-restricted.rs:31:1 + | +LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs new file mode 100644 index 00000000000..679cb772868 --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs new file mode 100644 index 00000000000..6484725814a --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/bang_proc_macro.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn bang_proc_macro(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.rs b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.rs index c2357d501ee..aa9eae0ba31 100644 --- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.rs @@ -3,8 +3,8 @@ extern crate derive_helper_shadowing; use derive_helper_shadowing::*; -#[derive(MyTrait)] #[my_attr] //~ ERROR `my_attr` is ambiguous +#[derive(MyTrait)] struct S; fn main() {} diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr index d597b577bb7..cdfecb3d101 100644 --- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr @@ -1,5 +1,5 @@ error[E0659]: `my_attr` is ambiguous - --> $DIR/derive-helper-shadowing.rs:7:3 + --> $DIR/derive-helper-shadowing.rs:6:3 | LL | #[my_attr] //~ ERROR `my_attr` is ambiguous | ^^^^^^^ ambiguous name @@ -10,7 +10,7 @@ note: `my_attr` could refer to the name imported here LL | use derive_helper_shadowing::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `my_attr` could also refer to the name defined here - --> $DIR/derive-helper-shadowing.rs:6:10 + --> $DIR/derive-helper-shadowing.rs:7:10 | LL | #[derive(MyTrait)] | ^^^^^^^ diff --git a/src/test/ui-fulldeps/proc-macro/macro-use-attr.rs b/src/test/ui-fulldeps/proc-macro/macro-use-attr.rs new file mode 100644 index 00000000000..904562e903d --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/macro-use-attr.rs @@ -0,0 +1,21 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// aux-build:attr_proc_macro.rs + +#[macro_use] extern crate attr_proc_macro; + +#[attr_proc_macro] +struct Foo; + +fn main() { + let _ = Foo; +} diff --git a/src/test/ui-fulldeps/proc-macro/macro-use-bang.rs b/src/test/ui-fulldeps/proc-macro/macro-use-bang.rs new file mode 100644 index 00000000000..9a54696d1f0 --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/macro-use-bang.rs @@ -0,0 +1,21 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// aux-build:bang_proc_macro.rs + +#![feature(proc_macro_non_items)] + +#[macro_use] +extern crate bang_proc_macro; + +fn main() { + bang_proc_macro!(println!("Hello, world!")); +} diff --git a/src/test/ui/E0596.ast.stderr b/src/test/ui/E0596.ast.stderr index d88530b2164..6aec37d4972 100644 --- a/src/test/ui/E0596.ast.stderr +++ b/src/test/ui/E0596.ast.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable --> $DIR/E0596.rs:16:18 | LL | let x = 1; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | let y = &mut x; //[ast]~ ERROR [E0596] | ^ cannot borrow mutably diff --git a/src/test/ui/asm/asm-out-assign-imm.nll.stderr b/src/test/ui/asm/asm-out-assign-imm.nll.stderr index 45b0c84275b..7fefb6672c7 100644 --- a/src/test/ui/asm/asm-out-assign-imm.nll.stderr +++ b/src/test/ui/asm/asm-out-assign-imm.nll.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/asm-out-assign-imm.rs:34:9 | LL | let x: isize; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x = 1; | ----- first assignment to `x` ... diff --git a/src/test/ui/assign-imm-local-twice.ast.nll.stderr b/src/test/ui/assign-imm-local-twice.ast.nll.stderr index 6d415eb7333..8a50ec8f52c 100644 --- a/src/test/ui/assign-imm-local-twice.ast.nll.stderr +++ b/src/test/ui/assign-imm-local-twice.ast.nll.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/assign-imm-local-twice.rs:20:5 + --> $DIR/assign-imm-local-twice.rs:21:5 | LL | let v: isize; - | - consider changing this to `mut v` -LL | //[mir]~^ NOTE consider changing this to `mut v` + | - help: make this binding mutable: `mut v` +... LL | v = 1; //[ast]~ NOTE first assignment | ----- first assignment to `v` ... diff --git a/src/test/ui/assign-imm-local-twice.ast.stderr b/src/test/ui/assign-imm-local-twice.ast.stderr index 32752621e14..a34ac54ae3b 100644 --- a/src/test/ui/assign-imm-local-twice.ast.stderr +++ b/src/test/ui/assign-imm-local-twice.ast.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/assign-imm-local-twice.rs:20:5 + --> $DIR/assign-imm-local-twice.rs:21:5 | LL | v = 1; //[ast]~ NOTE first assignment | ----- first assignment to `v` diff --git a/src/test/ui/assign-imm-local-twice.mir.stderr b/src/test/ui/assign-imm-local-twice.mir.stderr index 6d415eb7333..8a50ec8f52c 100644 --- a/src/test/ui/assign-imm-local-twice.mir.stderr +++ b/src/test/ui/assign-imm-local-twice.mir.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/assign-imm-local-twice.rs:20:5 + --> $DIR/assign-imm-local-twice.rs:21:5 | LL | let v: isize; - | - consider changing this to `mut v` -LL | //[mir]~^ NOTE consider changing this to `mut v` + | - help: make this binding mutable: `mut v` +... LL | v = 1; //[ast]~ NOTE first assignment | ----- first assignment to `v` ... diff --git a/src/test/ui/assign-imm-local-twice.rs b/src/test/ui/assign-imm-local-twice.rs index ee9dafdd49e..137414ccc6d 100644 --- a/src/test/ui/assign-imm-local-twice.rs +++ b/src/test/ui/assign-imm-local-twice.rs @@ -13,7 +13,8 @@ fn test() { let v: isize; - //[mir]~^ NOTE consider changing this to `mut v` + //[mir]~^ HELP make this binding mutable + //[mir]~| SUGGESTION mut v v = 1; //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment println!("v={}", v); diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr index 57a86227f76..64ac6883087 100644 --- a/src/test/ui/augmented-assignments.nll.stderr +++ b/src/test/ui/augmented-assignments.nll.stderr @@ -15,11 +15,11 @@ LL | | x; //~ value moved here | borrow later used here error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable - --> $DIR/augmented-assignments.rs:30:5 + --> $DIR/augmented-assignments.rs:31:5 | LL | let y = Int(2); | - help: consider changing this to be mutable: `mut y` -LL | //~^ consider changing this to `mut y` +... LL | y //~ error: cannot borrow immutable local variable `y` as mutable | ^ cannot borrow as mutable diff --git a/src/test/ui/augmented-assignments.rs b/src/test/ui/augmented-assignments.rs index 82f5c49eeb7..2857ff2554a 100644 --- a/src/test/ui/augmented-assignments.rs +++ b/src/test/ui/augmented-assignments.rs @@ -26,7 +26,8 @@ fn main() { x; //~ value moved here let y = Int(2); - //~^ consider changing this to `mut y` + //~^ HELP make this binding mutable + //~| SUGGESTION mut y y //~ error: cannot borrow immutable local variable `y` as mutable //~| cannot borrow += diff --git a/src/test/ui/augmented-assignments.stderr b/src/test/ui/augmented-assignments.stderr index 953af813c38..a7f3328071e 100644 --- a/src/test/ui/augmented-assignments.stderr +++ b/src/test/ui/augmented-assignments.stderr @@ -1,9 +1,9 @@ error[E0596]: cannot borrow immutable local variable `y` as mutable - --> $DIR/augmented-assignments.rs:30:5 + --> $DIR/augmented-assignments.rs:31:5 | LL | let y = Int(2); - | - consider changing this to `mut y` -LL | //~^ consider changing this to `mut y` + | - help: make this binding mutable: `mut y` +... LL | y //~ error: cannot borrow immutable local variable `y` as mutable | ^ cannot borrow mutably diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr new file mode 100644 index 00000000000..5f8b7007f30 --- /dev/null +++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.nll.stderr @@ -0,0 +1,11 @@ +error[E0008]: cannot bind by-move into a pattern guard + --> $DIR/bind-by-move-no-guards.rs:8:14 + | +LL | Some(z) if z.recv().unwrap() => { panic!() }, + | ^ moves value into pattern guard + | + = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs index bb6060f2543..bc9b3a8de4e 100644 --- a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs +++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs @@ -1,13 +1,3 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::sync::mpsc::channel; fn main() { diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr index ed516cd559e..2af2b0d660e 100644 --- a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr +++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr @@ -1,5 +1,5 @@ error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/bind-by-move-no-guards.rs:18:14 + --> $DIR/bind-by-move-no-guards.rs:8:14 | LL | Some(z) if z.recv().unwrap() => { panic!() }, | ^ moves value into pattern guard diff --git a/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr b/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr index b17245673e0..c2ecdb33ba9 100644 --- a/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr +++ b/src/test/ui/borrowck/borrowck-access-permissions.ast.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable --> $DIR/borrowck-access-permissions.rs:22:24 | LL | let x = 1; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | let _y1 = &mut x; //[ast]~ ERROR [E0596] | ^ cannot borrow mutably @@ -17,7 +17,7 @@ error[E0596]: cannot borrow immutable `Box` content `*box_x` as mutable --> $DIR/borrowck-access-permissions.rs:37:24 | LL | let box_x = Box::new(1); - | ----- consider changing this to `mut box_x` + | ----- help: make this binding mutable: `mut box_x` ... LL | let _y1 = &mut *box_x; //[ast]~ ERROR [E0596] | ^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/borrowck/borrowck-argument.stderr b/src/test/ui/borrowck/borrowck-argument.stderr index 2a7a7b3ffee..7b8849ec764 100644 --- a/src/test/ui/borrowck/borrowck-argument.stderr +++ b/src/test/ui/borrowck/borrowck-argument.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable --> $DIR/borrowck-argument.rs:20:5 | LL | fn func(arg: S) { - | --- consider changing this to `mut arg` + | --- help: make this binding mutable: `mut arg` LL | arg.mutate(); //~ ERROR: cannot borrow immutable argument | ^^^ cannot borrow mutably @@ -10,7 +10,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable --> $DIR/borrowck-argument.rs:25:9 | LL | fn method(&self, arg: S) { - | --- consider changing this to `mut arg` + | --- help: make this binding mutable: `mut arg` LL | arg.mutate(); //~ ERROR: cannot borrow immutable argument | ^^^ cannot borrow mutably @@ -18,7 +18,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable --> $DIR/borrowck-argument.rs:31:9 | LL | fn default(&self, arg: S) { - | --- consider changing this to `mut arg` + | --- help: make this binding mutable: `mut arg` LL | arg.mutate(); //~ ERROR: cannot borrow immutable argument | ^^^ cannot borrow mutably @@ -28,7 +28,7 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable LL | (|arg: S| { arg.mutate() })(s); //~ ERROR: cannot borrow immutable argument | --- ^^^ cannot borrow mutably | | - | consider changing this to `mut arg` + | help: make this binding mutable: `mut arg` error: aborting due to 4 previous errors diff --git a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr index 6936d32a789..b0f0535b9f6 100644 --- a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr @@ -28,7 +28,7 @@ LL | let x = 3; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | unsafe { LL | asm!("nop" : "=r"(x)); //[ast]~ ERROR cannot assign twice | ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable @@ -40,7 +40,7 @@ LL | let x = 3; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | unsafe { LL | asm!("nop" : "+r"(x)); //[ast]~ ERROR cannot assign twice | ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/borrowck/borrowck-asm.mir.stderr b/src/test/ui/borrowck/borrowck-asm.mir.stderr index 6936d32a789..b0f0535b9f6 100644 --- a/src/test/ui/borrowck/borrowck-asm.mir.stderr +++ b/src/test/ui/borrowck/borrowck-asm.mir.stderr @@ -28,7 +28,7 @@ LL | let x = 3; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | unsafe { LL | asm!("nop" : "=r"(x)); //[ast]~ ERROR cannot assign twice | ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable @@ -40,7 +40,7 @@ LL | let x = 3; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | unsafe { LL | asm!("nop" : "+r"(x)); //[ast]~ ERROR cannot assign twice | ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr index ca6b86e5ca6..a6338a22389 100644 --- a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr +++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:25:5 | LL | let x = Foo { x: 3 }; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.printme(); //~ ERROR cannot borrow | ^ cannot borrow mutably diff --git a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr index 9fc030f604c..19a96d56857 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr @@ -147,7 +147,7 @@ error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable --> $DIR/borrowck-borrow-from-owned-ptr.rs:132:21 | LL | let foo = make_foo(); - | --- consider changing this to `mut foo` + | --- help: make this binding mutable: `mut foo` LL | let bar1 = &mut foo.bar1; //~ ERROR cannot borrow | ^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr index cd0d6aa4ca3..75f12c377ed 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr @@ -114,7 +114,7 @@ error[E0596]: cannot borrow field `foo.bar1` of immutable binding as mutable --> $DIR/borrowck-borrow-from-stack-variable.rs:130:21 | LL | let foo = make_foo(); - | --- consider changing this to `mut foo` + | --- help: make this binding mutable: `mut foo` LL | let bar1 = &mut foo.bar1; //~ ERROR cannot borrow | ^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr index d852125a775..9f079b8cf98 100644 --- a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable `Box` content `*a` as mutable --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:22:5 | LL | let a: Box<_> = box A; - | - consider changing this to `mut a` + | - help: make this binding mutable: `mut a` LL | a.foo(); | ^ cannot borrow as mutable diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr index 0191e0765b3..2eeb4e433ad 100644 --- a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr @@ -5,7 +5,7 @@ LL | x => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -16,7 +16,7 @@ LL | E::Foo(x) => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -27,7 +27,7 @@ LL | S { bar: x } => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -38,7 +38,7 @@ LL | (x,) => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -49,7 +49,7 @@ LL | [x,_,_] => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr index 0191e0765b3..2eeb4e433ad 100644 --- a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr +++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr @@ -5,7 +5,7 @@ LL | x => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -16,7 +16,7 @@ LL | E::Foo(x) => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -27,7 +27,7 @@ LL | S { bar: x } => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -38,7 +38,7 @@ LL | (x,) => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable @@ -49,7 +49,7 @@ LL | [x,_,_] => { | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable `x` | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr index 0859a4e0f55..c073db2917a 100644 --- a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr +++ b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable --> $DIR/borrowck-mut-addr-of-imm-var.rs:13:30 | LL | let x: isize = 3; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | let y: &mut isize = &mut x; //~ ERROR cannot borrow | ^ cannot borrow mutably diff --git a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr index e2fd9d771f1..51b8ae83c61 100644 --- a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr +++ b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `v` as mutable --> $DIR/borrowck-mut-slice-of-imm-vec.rs:17:16 | LL | let v = vec![1, 2, 3]; - | - consider changing this to `mut v` + | - help: make this binding mutable: `mut v` LL | write(&mut v); //~ ERROR cannot borrow | ^ cannot borrow mutably diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr new file mode 100644 index 00000000000..b363a78cbc2 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr @@ -0,0 +1,24 @@ +error[E0302]: cannot assign in a pattern guard + --> $DIR/borrowck-mutate-in-guard.rs:20:25 + | +LL | Enum::A(_) if { x = Enum::B(false); false } => 1, + | ^^^^^^^^^^^^^^^^^^ assignment in pattern guard + +error[E0301]: cannot mutably borrow in a pattern guard + --> $DIR/borrowck-mutate-in-guard.rs:22:38 + | +LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, + | ^ borrowed mutably in pattern guard + | + = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable + +error[E0302]: cannot assign in a pattern guard + --> $DIR/borrowck-mutate-in-guard.rs:22:41 + | +LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, + | ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard + +error: aborting due to 3 previous errors + +Some errors occurred: E0301, E0302. +For more information about an error, try `rustc --explain E0301`. diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.stderr b/src/test/ui/borrowck/borrowck-overloaded-call.stderr index 213d78339e2..fa2473adc2f 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-call.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-call.stderr @@ -12,7 +12,7 @@ error[E0596]: cannot borrow immutable local variable `s` as mutable --> $DIR/borrowck-overloaded-call.rs:77:5 | LL | let s = SFnMut { - | - consider changing this to `mut s` + | - help: make this binding mutable: `mut s` ... LL | s(3); //~ ERROR cannot borrow immutable local variable `s` as mutable | ^ cannot borrow mutably diff --git a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr index 2e2a1224306..520992096b5 100644 --- a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr +++ b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow field `(x as std::prelude::v1::Some).0` of immutable --> $DIR/borrowck-ref-mut-of-imm.rs:14:12 | LL | fn destructure(x: Option) -> isize { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | Some(ref mut v) => *v //~ ERROR cannot borrow | ^^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr index 03b835d3077..0c067c47004 100644 --- a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr +++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr @@ -12,7 +12,7 @@ error[E0596]: cannot borrow immutable argument `f` as mutable --> $DIR/borrowck-unboxed-closures.rs:17:5 | LL | fn b isize>(f: F) { - | - consider changing this to `mut f` + | - help: make this binding mutable: `mut f` LL | f(1, 2); //~ ERROR cannot borrow immutable argument | ^ cannot borrow mutably diff --git a/src/test/ui/borrowck/immutable-arg.stderr b/src/test/ui/borrowck/immutable-arg.stderr index 1cf68795bf0..06ae5cdbcc6 100644 --- a/src/test/ui/borrowck/immutable-arg.stderr +++ b/src/test/ui/borrowck/immutable-arg.stderr @@ -10,7 +10,7 @@ error[E0384]: cannot assign to immutable argument `_x` (Mir) --> $DIR/immutable-arg.rs:14:5 | LL | fn foo(_x: u32) { - | -- consider changing this to `mut _x` + | -- help: make this binding mutable: `mut _x` LL | _x = 4; | ^^^^^^ cannot assign to immutable argument diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs index 2a94e05016d..9431ef5f13d 100644 --- a/src/test/ui/borrowck/issue-41962.rs +++ b/src/test/ui/borrowck/issue-41962.rs @@ -18,9 +18,6 @@ pub fn main(){ } //~^^ ERROR use of partially moved value: `maybe` (Ast) [E0382] //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382] - //~| ERROR use of moved value: `maybe` (Mir) [E0382] - //~| ERROR use of moved value: `maybe` (Mir) [E0382] //~| ERROR use of moved value (Mir) [E0382] - //~| ERROR borrow of moved value: `maybe` (Mir) [E0382] } } diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index b6e005a6673..957ccfe45dd 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -16,17 +16,6 @@ LL | if let Some(thing) = maybe { | = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `maybe` (Mir) - --> $DIR/issue-41962.rs:17:16 - | -LL | if let Some(thing) = maybe { - | ^^^^^-----^ - | | | - | | value moved here - | value used here after move - | - = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait - error[E0382]: use of moved value (Mir) --> $DIR/issue-41962.rs:17:21 | @@ -35,26 +24,6 @@ LL | if let Some(thing) = maybe { | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `maybe` (Mir) - --> $DIR/issue-41962.rs:17:30 - | -LL | if let Some(thing) = maybe { - | ----- ^^^^^ value used here after move - | | - | value moved here - | - = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait - -error[E0382]: borrow of moved value: `maybe` (Mir) - --> $DIR/issue-41962.rs:17:30 - | -LL | if let Some(thing) = maybe { - | ----- ^^^^^ value borrowed here after move - | | - | value moved here - | - = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr index d77254f3141..5013f877e7e 100644 --- a/src/test/ui/borrowck/mutability-errors.stderr +++ b/src/test/ui/borrowck/mutability-errors.stderr @@ -230,7 +230,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/mutability-errors.rs:64:10 | LL | fn imm_local(x: (i32,)) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | &mut x; //~ ERROR | ^ cannot borrow mutably @@ -238,7 +238,7 @@ error[E0596]: cannot borrow field `x.0` of immutable binding as mutable --> $DIR/mutability-errors.rs:65:10 | LL | fn imm_local(x: (i32,)) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | &mut x; //~ ERROR LL | &mut x.0; //~ ERROR | ^^^ cannot mutably borrow field of immutable binding @@ -247,7 +247,7 @@ error[E0595]: closure cannot assign to immutable argument `x` --> $DIR/mutability-errors.rs:69:5 | LL | fn imm_capture(x: (i32,)) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | || { //~ ERROR | ^^ cannot borrow mutably diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr index 54d12f8fae8..d16c0a5e37b 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding --> $DIR/reassignment_immutable_fields.rs:17:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.0 = 1; //~ ERROR | ^^^^^^^ cannot mutably borrow field of immutable binding @@ -10,7 +10,7 @@ error[E0594]: cannot assign to field `x.1` of immutable binding --> $DIR/reassignment_immutable_fields.rs:18:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.0 = 1; //~ ERROR LL | x.1 = 22; //~ ERROR | ^^^^^^^^ cannot mutably borrow field of immutable binding @@ -31,7 +31,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding --> $DIR/reassignment_immutable_fields.rs:25:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.0 = 1; //~ ERROR | ^^^^^^^ cannot mutably borrow field of immutable binding @@ -39,7 +39,7 @@ error[E0594]: cannot assign to field `x.1` of immutable binding --> $DIR/reassignment_immutable_fields.rs:26:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.0 = 1; //~ ERROR LL | x.1 = 22; //~ ERROR | ^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr index 70849905f92..b0b351889b7 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `x.a` of immutable binding --> $DIR/reassignment_immutable_fields_overlapping.rs:22:5 | LL | let x: Foo; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.a = 1; //~ ERROR | ^^^^^^^ cannot mutably borrow field of immutable binding @@ -10,7 +10,7 @@ error[E0594]: cannot assign to field `x.b` of immutable binding --> $DIR/reassignment_immutable_fields_overlapping.rs:23:5 | LL | let x: Foo; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.a = 1; //~ ERROR LL | x.b = 22; //~ ERROR | ^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr index b3c013d8b1f..65dff51059c 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding --> $DIR/reassignment_immutable_fields_twice.rs:17:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x = (22, 44); LL | x.0 = 1; //~ ERROR | ^^^^^^^ cannot mutably borrow field of immutable binding @@ -11,7 +11,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding --> $DIR/reassignment_immutable_fields_twice.rs:22:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.0 = 1; //~ ERROR | ^^^^^^^ cannot mutably borrow field of immutable binding @@ -19,7 +19,7 @@ error[E0594]: cannot assign to field `x.0` of immutable binding --> $DIR/reassignment_immutable_fields_twice.rs:23:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.0 = 1; //~ ERROR LL | x.0 = 22; //~ ERROR | ^^^^^^^^ cannot mutably borrow field of immutable binding @@ -28,7 +28,7 @@ error[E0594]: cannot assign to field `x.1` of immutable binding --> $DIR/reassignment_immutable_fields_twice.rs:24:5 | LL | let x: (u32, u32); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | x.1 = 44; //~ ERROR | ^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index 68818f50cd2..42eb1e9cb21 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable --> $DIR/huge_multispan_highlight.rs:100:18 | LL | let x = "foo"; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | let y = &mut x; //~ ERROR cannot borrow | ^ cannot borrow mutably diff --git a/src/test/ui/command-line-diagnostics.nll.stderr b/src/test/ui/command-line-diagnostics.nll.stderr index 46bb7c5af57..6273ba33e16 100644 --- a/src/test/ui/command-line-diagnostics.nll.stderr +++ b/src/test/ui/command-line-diagnostics.nll.stderr @@ -5,7 +5,7 @@ LL | let x = 42; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x = 43; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 4a29cd81425..591c3a0df03 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow field `f.v` of immutable binding as mutable --> $DIR/issue-35937.rs:17:5 | LL | let f = Foo { v: Vec::new() }; - | - consider changing this to `mut f` + | - help: make this binding mutable: `mut f` LL | f.v.push("cat".to_string()); //~ ERROR cannot borrow | ^^^ cannot mutably borrow field of immutable binding @@ -10,7 +10,7 @@ error[E0594]: cannot assign to field `s.x` of immutable binding --> $DIR/issue-35937.rs:26:5 | LL | let s = S { x: 42 }; - | - consider changing this to `mut s` + | - help: make this binding mutable: `mut s` LL | s.x += 1; //~ ERROR cannot assign | ^^^^^^^^ cannot mutably borrow field of immutable binding @@ -18,7 +18,7 @@ error[E0594]: cannot assign to field `s.x` of immutable binding --> $DIR/issue-35937.rs:30:5 | LL | fn bar(s: S) { - | - consider changing this to `mut s` + | - help: make this binding mutable: `mut s` LL | s.x += 1; //~ ERROR cannot assign | ^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index dfa9cb880e5..7cf2ca720ef 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow field `z.x` of immutable binding as mutable --> $DIR/issue-39544.rs:21:18 | LL | let z = Z { x: X::Y }; - | - consider changing this to `mut z` + | - help: make this binding mutable: `mut z` LL | let _ = &mut z.x; //~ ERROR cannot borrow | ^^^ cannot mutably borrow field of immutable binding @@ -77,7 +77,7 @@ error[E0596]: cannot borrow field `z.x` of immutable binding as mutable --> $DIR/issue-39544.rs:51:18 | LL | pub fn with_arg(z: Z, w: &Z) { - | - consider changing this to `mut z` + | - help: make this binding mutable: `mut z` LL | let _ = &mut z.x; //~ ERROR cannot borrow | ^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs new file mode 100644 index 00000000000..d053b11772c --- /dev/null +++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs @@ -0,0 +1,66 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn test_and() { + let a = true; + let b = false; + if a and b { + //~^ ERROR expected `{`, found `and` + println!("both"); + } +} + +fn test_or() { + let a = true; + let b = false; + if a or b { + //~^ ERROR expected `{`, found `or` + println!("both"); + } +} + +fn test_and_par() { + let a = true; + let b = false; + if (a and b) { + //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and` + println!("both"); + } +} + +fn test_or_par() { + let a = true; + let b = false; + if (a or b) { + //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or` + println!("both"); + } +} + +fn test_while_and() { + let a = true; + let b = false; + while a and b { + //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and` + println!("both"); + } +} + +fn test_while_or() { + let a = true; + let b = false; + while a or b { + //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or` + println!("both"); + } +} + +fn main() { +} diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr new file mode 100644 index 00000000000..22845775aed --- /dev/null +++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr @@ -0,0 +1,54 @@ +error: expected `{`, found `and` + --> $DIR/issue-54109-and_instead_of_ampersands.rs:14:10 + | +LL | if a and b { + | -- ^^^ help: use `&&` instead of `and` for the boolean operator + | | + | this `if` statement has a condition, but no block + +error: expected `{`, found `or` + --> $DIR/issue-54109-and_instead_of_ampersands.rs:23:10 + | +LL | if a or b { + | -- ^^ help: use `||` instead of `or` for the boolean operator + | | + | this `if` statement has a condition, but no block + +error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and` + --> $DIR/issue-54109-and_instead_of_ampersands.rs:32:11 + | +LL | if (a and b) { + | ^^^ + | | + | expected one of 8 possible tokens here + | help: use `&&` instead of `and` for the boolean operator + +error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or` + --> $DIR/issue-54109-and_instead_of_ampersands.rs:41:11 + | +LL | if (a or b) { + | ^^ + | | + | expected one of 8 possible tokens here + | help: use `||` instead of `or` for the boolean operator + +error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and` + --> $DIR/issue-54109-and_instead_of_ampersands.rs:50:13 + | +LL | while a and b { + | ^^^ + | | + | expected one of `!`, `.`, `::`, `?`, `{`, or an operator here + | help: use `&&` instead of `and` for the boolean operator + +error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or` + --> $DIR/issue-54109-and_instead_of_ampersands.rs:59:13 + | +LL | while a or b { + | ^^ + | | + | expected one of `!`, `.`, `::`, `?`, `{`, or an operator here + | help: use `||` instead of `or` for the boolean operator + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/error-codes/E0008.nll.stderr b/src/test/ui/error-codes/E0008.nll.stderr new file mode 100644 index 00000000000..ce627cb741a --- /dev/null +++ b/src/test/ui/error-codes/E0008.nll.stderr @@ -0,0 +1,11 @@ +error[E0008]: cannot bind by-move into a pattern guard + --> $DIR/E0008.rs:13:14 + | +LL | Some(s) if s.len() == 0 => {}, + | ^ moves value into pattern guard + | + = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/error-codes/E0301.nll.stderr b/src/test/ui/error-codes/E0301.nll.stderr new file mode 100644 index 00000000000..f060eb90435 --- /dev/null +++ b/src/test/ui/error-codes/E0301.nll.stderr @@ -0,0 +1,11 @@ +error[E0301]: cannot mutably borrow in a pattern guard + --> $DIR/E0301.rs:14:19 + | +LL | option if option.take().is_none() => {}, //~ ERROR E0301 + | ^^^^^^ borrowed mutably in pattern guard + | + = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0301`. diff --git a/src/test/ui/feature-gates/feature-gate-crate_in_paths.rs b/src/test/ui/feature-gates/feature-gate-crate_in_paths.rs deleted file mode 100644 index e667dab621b..00000000000 --- a/src/test/ui/feature-gates/feature-gate-crate_in_paths.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S; - -fn main() { - let _ = crate::S; //~ ERROR `crate` in paths is experimental -} diff --git a/src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr b/src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr deleted file mode 100644 index 32115ba2111..00000000000 --- a/src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: `crate` in paths is experimental (see issue #45477) - --> $DIR/feature-gate-crate_in_paths.rs:14:13 - | -LL | let _ = crate::S; //~ ERROR `crate` in paths is experimental - | ^^^^^ - | - = help: add #![feature(crate_in_paths)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr b/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr index 80d81ea03cb..d3d5bd498cf 100644 --- a/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr +++ b/src/test/ui/feature-gates/feature-gate-dropck-ugeh-2.stderr @@ -2,7 +2,7 @@ error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_bli --> $DIR/feature-gate-dropck-ugeh-2.rs:17:5 | LL | #[unsafe_destructor_blind_to_params] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]` | note: lint level defined here --> $DIR/feature-gate-dropck-ugeh-2.rs:11:9 diff --git a/src/test/ui/feature-gates/feature-gate-panic-implementation.rs b/src/test/ui/feature-gates/feature-gate-panic-implementation.rs index 84e5f302c16..ca51154884f 100644 --- a/src/test/ui/feature-gates/feature-gate-panic-implementation.rs +++ b/src/test/ui/feature-gates/feature-gate-panic-implementation.rs @@ -15,7 +15,7 @@ use core::panic::PanicInfo; -#[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489) +#[panic_implementation] //~ ERROR this attribute was renamed to `panic_handler` (see issue #44489) fn panic(info: &PanicInfo) -> ! { loop {} } diff --git a/src/test/ui/feature-gates/feature-gate-panic-implementation.stderr b/src/test/ui/feature-gates/feature-gate-panic-implementation.stderr index 926a49ae831..a54780468c4 100644 --- a/src/test/ui/feature-gates/feature-gate-panic-implementation.stderr +++ b/src/test/ui/feature-gates/feature-gate-panic-implementation.stderr @@ -1,7 +1,7 @@ -error[E0658]: This attribute was renamed to `panic_handler` (see issue #44489) +error[E0658]: this attribute was renamed to `panic_handler` (see issue #44489) --> $DIR/feature-gate-panic-implementation.rs:18:1 | -LL | #[panic_implementation] //~ ERROR This attribute was renamed to `panic_handler` (see issue #44489) +LL | #[panic_implementation] //~ ERROR this attribute was renamed to `panic_handler` (see issue #44489) | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(panic_implementation)] to the crate attributes to enable diff --git a/src/test/ui/hygiene/dollar-crate-modern.stderr b/src/test/ui/hygiene/dollar-crate-modern.stderr new file mode 100644 index 00000000000..5fa7d8eda1d --- /dev/null +++ b/src/test/ui/hygiene/dollar-crate-modern.stderr @@ -0,0 +1,8 @@ +warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable + --> $DIR/dollar-crate-modern.rs:16:24 + | +LL | #![feature(decl_macro, crate_in_paths)] + | ^^^^^^^^^^^^^^ + | + = note: #[warn(stable_features)] on by default + diff --git a/src/test/ui/immut-function-arguments.ast.stderr b/src/test/ui/immut-function-arguments.ast.stderr index 54125b955cb..7b2061950f3 100644 --- a/src/test/ui/immut-function-arguments.ast.stderr +++ b/src/test/ui/immut-function-arguments.ast.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable `Box` content `*y` --> $DIR/immut-function-arguments.rs:15:5 | LL | fn f(y: Box) { - | - consider changing this to `mut y` + | - help: make this binding mutable: `mut y` LL | *y = 5; //[ast]~ ERROR cannot assign | ^^^^^^ cannot borrow as mutable @@ -12,7 +12,7 @@ error[E0594]: cannot assign to immutable `Box` content `*q` LL | let _frob = |q: Box| { *q = 2; }; //[ast]~ ERROR cannot assign | - ^^^^^^ cannot borrow as mutable | | - | consider changing this to `mut q` + | help: make this binding mutable: `mut q` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 1e3e997b111..3019e3aa1f7 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -11,12 +11,18 @@ error: unsatisfied lifetime constraints | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` +help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint + | +LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ^^^^^^^^^^^^^^ error: unsatisfied lifetime constraints --> $DIR/must_outlive_least_region_or_bound.rs:22:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` error: unsatisfied lifetime constraints --> $DIR/must_outlive_least_region_or_bound.rs:29:5 diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index d75de81fc1c..4bc8876c232 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -5,6 +5,10 @@ LL | fn iter_values_anon(&self) -> impl Iterator { | - let's call the lifetime of this reference `'1` LL | self.x.iter().map(|a| a.0) | ^^^^^^ cast requires that `'1` must outlive `'static` +help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint + | +LL | fn iter_values_anon(&self) -> impl Iterator + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:21:9 @@ -13,6 +17,10 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -- lifetime `'a` defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^ cast requires that `'a` must outlive `'static` +help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint + | +LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-17385.nll.stderr b/src/test/ui/issues/issue-17385.nll.stderr index 85924a75261..c7b0b57000f 100644 --- a/src/test/ui/issues/issue-17385.nll.stderr +++ b/src/test/ui/issues/issue-17385.nll.stderr @@ -1,23 +1,3 @@ -error[E0382]: use of moved value: `foo` - --> $DIR/issue-17385.rs:28:11 - | -LL | drop(foo); - | --- value moved here -LL | match foo { //~ ERROR use of moved value - | ^^^ value used here after move - | - = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait - -error[E0382]: borrow of moved value: `foo` - --> $DIR/issue-17385.rs:28:11 - | -LL | drop(foo); - | --- value moved here -LL | match foo { //~ ERROR use of moved value - | ^^^ value borrowed here after move - | - = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait - error[E0382]: use of moved value: `foo.0` --> $DIR/issue-17385.rs:29:11 | @@ -39,27 +19,6 @@ LL | match e { //~ ERROR use of moved value | = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait -error[E0382]: borrow of moved value: `e` - --> $DIR/issue-17385.rs:35:11 - | -LL | drop(e); - | - value moved here -LL | match e { //~ ERROR use of moved value - | ^ value borrowed here after move - | - = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait - -error[E0382]: use of moved value: `e` - --> $DIR/issue-17385.rs:36:9 - | -LL | drop(e); - | - value moved here -LL | match e { //~ ERROR use of moved value -LL | Enum::Variant1 => unreachable!(), - | ^^^^^^^^^^^^^^ value used here after move - | - = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/issues/issue-36400.stderr b/src/test/ui/issues/issue-36400.stderr index dbd6999b4f2..b0aadf3a514 100644 --- a/src/test/ui/issues/issue-36400.stderr +++ b/src/test/ui/issues/issue-36400.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable --> $DIR/issue-36400.rs:15:12 | LL | let x = Box::new(3); - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | f(&mut *x); //~ ERROR cannot borrow immutable | ^^ cannot borrow as mutable diff --git a/src/test/ui/issues/issue-45199.ast.nll.stderr b/src/test/ui/issues/issue-45199.ast.nll.stderr index ce39776252b..3c7e92e2bc9 100644 --- a/src/test/ui/issues/issue-45199.ast.nll.stderr +++ b/src/test/ui/issues/issue-45199.ast.nll.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:19:5 + --> $DIR/issue-45199.rs:20:5 | LL | let b: Box; - | - consider changing this to `mut b` -LL | //[mir]~^ NOTE consider changing this to `mut b` + | - help: make this binding mutable: `mut b` +... LL | b = Box::new(1); //[ast]~ NOTE first assignment | - first assignment to `b` LL | //[mir]~^ NOTE first assignment @@ -11,23 +11,23 @@ LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable var | ^ cannot assign twice to immutable variable error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:29:5 + --> $DIR/issue-45199.rs:31:5 | LL | let b = Box::new(1); //[ast]~ NOTE first assignment | - | | | first assignment to `b` - | consider changing this to `mut b` + | help: make this binding mutable: `mut b` ... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^ cannot assign twice to immutable variable error[E0384]: cannot assign to immutable argument `b` - --> $DIR/issue-45199.rs:37:5 + --> $DIR/issue-45199.rs:40:5 | LL | fn test_args(b: Box) { //[ast]~ NOTE first assignment - | - consider changing this to `mut b` -LL | //[mir]~^ NOTE consider changing this to `mut b` + | - help: make this binding mutable: `mut b` +... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^ cannot assign to immutable argument diff --git a/src/test/ui/issues/issue-45199.ast.stderr b/src/test/ui/issues/issue-45199.ast.stderr index ff8f78b5116..cf8ceacca57 100644 --- a/src/test/ui/issues/issue-45199.ast.stderr +++ b/src/test/ui/issues/issue-45199.ast.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:19:5 + --> $DIR/issue-45199.rs:20:5 | LL | b = Box::new(1); //[ast]~ NOTE first assignment | --------------- first assignment to `b` @@ -8,7 +8,7 @@ LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable var | ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:29:5 + --> $DIR/issue-45199.rs:31:5 | LL | let b = Box::new(1); //[ast]~ NOTE first assignment | - first assignment to `b` @@ -17,11 +17,11 @@ LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable | ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:37:5 + --> $DIR/issue-45199.rs:40:5 | LL | fn test_args(b: Box) { //[ast]~ NOTE first assignment | - first assignment to `b` -LL | //[mir]~^ NOTE consider changing this to `mut b` +... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/issues/issue-45199.mir.stderr b/src/test/ui/issues/issue-45199.mir.stderr index ce39776252b..3c7e92e2bc9 100644 --- a/src/test/ui/issues/issue-45199.mir.stderr +++ b/src/test/ui/issues/issue-45199.mir.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:19:5 + --> $DIR/issue-45199.rs:20:5 | LL | let b: Box; - | - consider changing this to `mut b` -LL | //[mir]~^ NOTE consider changing this to `mut b` + | - help: make this binding mutable: `mut b` +... LL | b = Box::new(1); //[ast]~ NOTE first assignment | - first assignment to `b` LL | //[mir]~^ NOTE first assignment @@ -11,23 +11,23 @@ LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable var | ^ cannot assign twice to immutable variable error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/issue-45199.rs:29:5 + --> $DIR/issue-45199.rs:31:5 | LL | let b = Box::new(1); //[ast]~ NOTE first assignment | - | | | first assignment to `b` - | consider changing this to `mut b` + | help: make this binding mutable: `mut b` ... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^ cannot assign twice to immutable variable error[E0384]: cannot assign to immutable argument `b` - --> $DIR/issue-45199.rs:37:5 + --> $DIR/issue-45199.rs:40:5 | LL | fn test_args(b: Box) { //[ast]~ NOTE first assignment - | - consider changing this to `mut b` -LL | //[mir]~^ NOTE consider changing this to `mut b` + | - help: make this binding mutable: `mut b` +... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^ cannot assign to immutable argument diff --git a/src/test/ui/issues/issue-45199.rs b/src/test/ui/issues/issue-45199.rs index 61e19ffc0d2..90a4960cb63 100644 --- a/src/test/ui/issues/issue-45199.rs +++ b/src/test/ui/issues/issue-45199.rs @@ -13,7 +13,8 @@ fn test_drop_replace() { let b: Box; - //[mir]~^ NOTE consider changing this to `mut b` + //[mir]~^ HELP make this binding mutable + //[mir]~| SUGGESTION mut b b = Box::new(1); //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable @@ -25,7 +26,8 @@ fn test_drop_replace() { fn test_call() { let b = Box::new(1); //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment - //[mir]~| NOTE consider changing this to `mut b` + //[mir]~| HELP make this binding mutable + //[mir]~| SUGGESTION mut b b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `b` //[ast]~| NOTE cannot assign twice to immutable @@ -33,7 +35,8 @@ fn test_call() { } fn test_args(b: Box) { //[ast]~ NOTE first assignment - //[mir]~^ NOTE consider changing this to `mut b` + //[mir]~^ HELP make this binding mutable + //[mir]~| SUGGESTION mut b b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign to immutable argument `b` //[ast]~| NOTE cannot assign twice to immutable diff --git a/src/test/ui/issues/issue-52489.rs b/src/test/ui/issues/issue-52489.rs index c43cc12ca02..f26392e82ac 100644 --- a/src/test/ui/issues/issue-52489.rs +++ b/src/test/ui/issues/issue-52489.rs @@ -10,6 +10,7 @@ // edition:2018 // aux-build:issue-52489.rs +// compile-flags:--extern issue_52489 use issue_52489; //~^ ERROR use of unstable library feature 'issue_52489_unstable' diff --git a/src/test/ui/issues/issue-52489.stderr b/src/test/ui/issues/issue-52489.stderr index 5b38a0789ad..b8c41d82643 100644 --- a/src/test/ui/issues/issue-52489.stderr +++ b/src/test/ui/issues/issue-52489.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'issue_52489_unstable' - --> $DIR/issue-52489.rs:14:5 + --> $DIR/issue-52489.rs:15:5 | LL | use issue_52489; | ^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-53675-a-test-called-panic.rs b/src/test/ui/issues/issue-53675-a-test-called-panic.rs new file mode 100644 index 00000000000..8a35b36d46d --- /dev/null +++ b/src/test/ui/issues/issue-53675-a-test-called-panic.rs @@ -0,0 +1,36 @@ +// rust-lang/rust#53675: At one point the compiler errored when a test +// named `panic` used the `assert!` macro in expression position. + +// compile-pass +// compile-flags: --test + +mod in_expression_position { + #[test] + fn panic() { + assert!(true) + } +} + +mod in_statement_position { + #[test] + fn panic() { + assert!(true); + } +} + +mod what_if_we_use_panic_directly_in_expr { + #[test] + #[should_panic] + fn panic() { + panic!("in expr") + } +} + + +mod what_if_we_use_panic_directly_in_stmt { + #[test] + #[should_panic] + fn panic() { + panic!("in stmt"); + } +} diff --git a/src/test/ui/issues/issue-53712.rs b/src/test/ui/issues/issue-53712.rs new file mode 100644 index 00000000000..2353904d79d --- /dev/null +++ b/src/test/ui/issues/issue-53712.rs @@ -0,0 +1,9 @@ +// issue #53712: make the error generated by using tuple indexing on an array more specific + +fn main() { + let arr = [10, 20, 30, 40, 50]; + arr.0; + //~^ ERROR no field `0` on type `[{integer}; 5]` [E0609] + //~| HELP instead of using tuple indexing, use array indexing + //~| SUGGESTION arr[0] +} diff --git a/src/test/ui/issues/issue-53712.stderr b/src/test/ui/issues/issue-53712.stderr new file mode 100644 index 00000000000..db85919afcb --- /dev/null +++ b/src/test/ui/issues/issue-53712.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `0` on type `[{integer}; 5]` + --> $DIR/issue-53712.rs:5:9 + | +LL | arr.0; + | ----^ + | | + | help: instead of using tuple indexing, use array indexing: `arr[0]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/issues/issue-5500-1.ast.stderr b/src/test/ui/issues/issue-5500-1.ast.stderr index 611eea533b2..5ea18af7c68 100644 --- a/src/test/ui/issues/issue-5500-1.ast.stderr +++ b/src/test/ui/issues/issue-5500-1.ast.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `_iter.node` of immutable binding --> $DIR/issue-5500-1.rs:22:5 | LL | let _iter = TrieMapIterator{node: &a}; - | ----- consider changing this to `mut _iter` + | ----- help: make this binding mutable: `mut _iter` LL | / _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding LL | | //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast) LL | | // MIR doesn't generate an error because the code isn't reachable. This is OK diff --git a/src/test/ui/issues/issue-5500-1.mir.stderr b/src/test/ui/issues/issue-5500-1.mir.stderr index 465485e5e29..5cb72794961 100644 --- a/src/test/ui/issues/issue-5500-1.mir.stderr +++ b/src/test/ui/issues/issue-5500-1.mir.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `_iter.node` of immutable binding (Ast) --> $DIR/issue-5500-1.rs:22:5 | LL | let _iter = TrieMapIterator{node: &a}; - | ----- consider changing this to `mut _iter` + | ----- help: make this binding mutable: `mut _iter` LL | / _iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding LL | | //[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast) LL | | // MIR doesn't generate an error because the code isn't reachable. This is OK diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr index 749b5760929..1a5f788e143 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr @@ -12,7 +12,7 @@ error[E0384]: cannot assign to immutable argument `y` --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5 | LL | fn foo(mut x: Ref, y: &u32) { - | - consider changing this to `mut y` + | - help: make this binding mutable: `mut y` LL | y = x.b; //~ ERROR lifetime mismatch | ^^^^^^^ cannot assign to immutable argument diff --git a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr index 0620235371a..fd3ae53d6ed 100644 --- a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr @@ -33,7 +33,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:23:9 | LL | let x; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | x = 2; | ----- first assignment to `x` @@ -44,7 +44,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:35:13 | LL | let x; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | x = 2; | ----- first assignment to `x` @@ -55,7 +55,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:45:13 | LL | let x; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | x = 1; //~ ERROR (Ast) [E0384] | ^^^^^ cannot assign twice to immutable variable @@ -64,7 +64,7 @@ error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:48:13 | LL | let x; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | x = 1; //~ ERROR (Ast) [E0384] | ----- first assignment to `x` diff --git a/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs new file mode 100644 index 00000000000..e4be1edc5d7 --- /dev/null +++ b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs @@ -0,0 +1,14 @@ +// compile-pass + +#![forbid(non_camel_case_types)] +#![allow(dead_code)] + +// None of the following types should generate a warning +struct _X {} +struct __X {} +struct __ {} +struct X_ {} +struct X__ {} +struct X___ {} + +fn main() { } diff --git a/src/test/ui/lint/lint-non-camel-case-types.rs b/src/test/ui/lint/lint-non-camel-case-types.rs index 5dcdf3a863f..2f0b6c57d55 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.rs +++ b/src/test/ui/lint/lint-non-camel-case-types.rs @@ -43,8 +43,6 @@ struct foo7 { bar: isize, } -type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase` - struct X86_64; struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64` diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr index 85610dc7fa3..05834a66cd0 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.stderr +++ b/src/test/ui/lint/lint-non-camel-case-types.stderr @@ -60,29 +60,23 @@ error: type parameter `ty` should have a camel case name such as `Ty` LL | fn f(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty` | ^^ -error: type `__` should have a camel case name such as `CamelCase` - --> $DIR/lint-non-camel-case-types.rs:46:1 - | -LL | type __ = isize; //~ ERROR type `__` should have a camel case name such as `CamelCase` - | ^^^^^^^^^^^^^^^^ - error: type `X86__64` should have a camel case name such as `X86_64` - --> $DIR/lint-non-camel-case-types.rs:50:1 + --> $DIR/lint-non-camel-case-types.rs:48:1 | LL | struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64` | ^^^^^^^^^^^^^^^ error: type `Abc_123` should have a camel case name such as `Abc123` - --> $DIR/lint-non-camel-case-types.rs:52:1 + --> $DIR/lint-non-camel-case-types.rs:50:1 | LL | struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123` | ^^^^^^^^^^^^^^^ error: type `A1_b2_c3` should have a camel case name such as `A1B2C3` - --> $DIR/lint-non-camel-case-types.rs:54:1 + --> $DIR/lint-non-camel-case-types.rs:52:1 | LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3` | ^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr index 58a76bd2cf3..b23225adbb4 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr @@ -1,8 +1,8 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-in-loop.rs:18:9 + --> $DIR/liveness-assign-imm-local-in-loop.rs:19:9 | LL | let v: isize; - | - consider changing this to `mut v` + | - help: make this binding mutable: `mut v` ... LL | v = 1; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr index 54419fd5b25..54135ca78ea 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-in-loop.rs:18:9 + --> $DIR/liveness-assign-imm-local-in-loop.rs:19:9 | LL | v = 1; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr index 58a76bd2cf3..b23225adbb4 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr @@ -1,8 +1,8 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-in-loop.rs:18:9 + --> $DIR/liveness-assign-imm-local-in-loop.rs:19:9 | LL | let v: isize; - | - consider changing this to `mut v` + | - help: make this binding mutable: `mut v` ... LL | v = 1; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs index 7bc3680ca77..6f44d67e823 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs @@ -13,7 +13,8 @@ fn test() { let v: isize; - //[mir]~^ NOTE consider changing this to `mut v` + //[mir]~^ HELP make this binding mutable + //[mir]~| SUGGESTION mut v loop { v = 1; //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr index 091547ed122..3dabbcb816b 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-in-op-eq.rs:19:5 + --> $DIR/liveness-assign-imm-local-in-op-eq.rs:20:5 | LL | let v: isize; - | - consider changing this to `mut v` -LL | //[mir]~^ NOTE consider changing this to `mut v` + | - help: make this binding mutable: `mut v` +... LL | v = 2; //[ast]~ NOTE first assignment | ----- first assignment to `v` LL | //[mir]~^ NOTE first assignment diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr index a98c3c29bd2..266fb63c7c7 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-in-op-eq.rs:19:5 + --> $DIR/liveness-assign-imm-local-in-op-eq.rs:20:5 | LL | v = 2; //[ast]~ NOTE first assignment | ----- first assignment to `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr index 091547ed122..3dabbcb816b 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-in-op-eq.rs:19:5 + --> $DIR/liveness-assign-imm-local-in-op-eq.rs:20:5 | LL | let v: isize; - | - consider changing this to `mut v` -LL | //[mir]~^ NOTE consider changing this to `mut v` + | - help: make this binding mutable: `mut v` +... LL | v = 2; //[ast]~ NOTE first assignment | ----- first assignment to `v` LL | //[mir]~^ NOTE first assignment diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs index 7812cdd8684..f585da8a3a5 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs @@ -13,7 +13,8 @@ fn test() { let v: isize; - //[mir]~^ NOTE consider changing this to `mut v` + //[mir]~^ HELP make this binding mutable + //[mir]~| SUGGESTION mut v v = 2; //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment v += 1; //[ast]~ ERROR cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr index e954b1f5e0f..4a2b3b5d5fe 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr @@ -1,11 +1,11 @@ error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/liveness-assign-imm-local-with-drop.rs:19:5 + --> $DIR/liveness-assign-imm-local-with-drop.rs:20:5 | LL | let b = Box::new(1); //[ast]~ NOTE first assignment | - | | | first assignment to `b` - | consider changing this to `mut b` + | help: make this binding mutable: `mut b` ... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr index 6abcf175f48..94799d919ae 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/liveness-assign-imm-local-with-drop.rs:19:5 + --> $DIR/liveness-assign-imm-local-with-drop.rs:20:5 | LL | let b = Box::new(1); //[ast]~ NOTE first assignment | - first assignment to `b` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr index e954b1f5e0f..4a2b3b5d5fe 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr @@ -1,11 +1,11 @@ error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/liveness-assign-imm-local-with-drop.rs:19:5 + --> $DIR/liveness-assign-imm-local-with-drop.rs:20:5 | LL | let b = Box::new(1); //[ast]~ NOTE first assignment | - | | | first assignment to `b` - | consider changing this to `mut b` + | help: make this binding mutable: `mut b` ... LL | b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable | ^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs index bb61a9037d9..c32d2c4bb0f 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs @@ -14,7 +14,8 @@ fn test() { let b = Box::new(1); //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment - //[mir]~| NOTE consider changing this to `mut b` + //[mir]~| HELP make this binding mutable + //[mir]~| SUGGESTION mut b drop(b); b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `b` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr index 70a6ab3edf8..6137c9f5882 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr @@ -1,11 +1,11 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-with-init.rs:19:5 + --> $DIR/liveness-assign-imm-local-with-init.rs:20:5 | LL | let v: isize = 1; //[ast]~ NOTE first assignment | - | | | first assignment to `v` - | consider changing this to `mut v` + | help: make this binding mutable: `mut v` ... LL | v = 2; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr index 47c780e83e8..d48608684a2 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr @@ -1,5 +1,5 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-with-init.rs:19:5 + --> $DIR/liveness-assign-imm-local-with-init.rs:20:5 | LL | let v: isize = 1; //[ast]~ NOTE first assignment | - first assignment to `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr index 70a6ab3edf8..6137c9f5882 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr @@ -1,11 +1,11 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/liveness-assign-imm-local-with-init.rs:19:5 + --> $DIR/liveness-assign-imm-local-with-init.rs:20:5 | LL | let v: isize = 1; //[ast]~ NOTE first assignment | - | | | first assignment to `v` - | consider changing this to `mut v` + | help: make this binding mutable: `mut v` ... LL | v = 2; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs index 672e9fab837..158eb7d428c 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs @@ -14,7 +14,8 @@ fn test() { let v: isize = 1; //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment - //[mir]~| NOTE consider changing this to `mut v` + //[mir]~| HELP make this binding mutable + //[mir]~| SUGGESTION mut v v.clone(); v = 2; //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/ui/liveness/liveness-move-in-while.nll.stderr b/src/test/ui/liveness/liveness-move-in-while.nll.stderr index 5ca5dc64709..9f1ffd91518 100644 --- a/src/test/ui/liveness/liveness-move-in-while.nll.stderr +++ b/src/test/ui/liveness/liveness-move-in-while.nll.stderr @@ -8,14 +8,6 @@ LL | while true { while true { while true { x = y; x.clone(); } } } | = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `y` - --> $DIR/liveness-move-in-while.rs:18:52 - | -LL | while true { while true { while true { x = y; x.clone(); } } } - | ^ value moved here in previous iteration of loop - | - = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/macros/macro-path-prelude-pass.stderr b/src/test/ui/macros/macro-path-prelude-pass.stderr new file mode 100644 index 00000000000..edae6a3e3cd --- /dev/null +++ b/src/test/ui/macros/macro-path-prelude-pass.stderr @@ -0,0 +1,8 @@ +warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable + --> $DIR/macro-path-prelude-pass.rs:13:12 + | +LL | #![feature(extern_prelude)] + | ^^^^^^^^^^^^^^ + | + = note: #[warn(stable_features)] on by default + diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr index c67095d9ee7..d3ba6fc005e 100644 --- a/src/test/ui/macros/span-covering-argument-1.stderr +++ b/src/test/ui/macros/span-covering-argument-1.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `foo` as mutable --> $DIR/span-covering-argument-1.rs:15:19 | LL | let $s = 0; - | -- consider changing this to `mut $s` + | -- help: make this binding mutable: `mut $s` LL | *&mut $s = 0; | ^^ cannot borrow mutably ... diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.rs b/src/test/ui/mismatched_types/numeric-literal-cast.rs new file mode 100644 index 00000000000..516b2e8dd30 --- /dev/null +++ b/src/test/ui/mismatched_types/numeric-literal-cast.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(_: u16) {} +fn foo1(_: f64) {} +fn foo2(_: i32) {} + +fn main() { + foo(1u8); + foo1(2f32); + foo2(3i16); +} + diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.stderr b/src/test/ui/mismatched_types/numeric-literal-cast.stderr new file mode 100644 index 00000000000..e2fe1a0914d --- /dev/null +++ b/src/test/ui/mismatched_types/numeric-literal-cast.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:16:9 + | +LL | foo(1u8); + | ^^^ expected u16, found u8 +help: change the type of the numeric literal from `u8` to `u16` + | +LL | foo(1u16); + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:17:10 + | +LL | foo1(2f32); + | ^^^^ expected f64, found f32 +help: change the type of the numeric literal from `f32` to `f64` + | +LL | foo1(2f64); + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:18:10 + | +LL | foo2(3i16); + | ^^^^ expected i32, found i16 +help: change the type of the numeric literal from `i16` to `i32` + | +LL | foo2(3i32); + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr index 0df303eed77..8b8414b8f1b 100644 --- a/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr +++ b/src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr @@ -5,7 +5,7 @@ LL | let &mut x = foo; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr index 0df303eed77..8b8414b8f1b 100644 --- a/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr +++ b/src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr @@ -5,7 +5,7 @@ LL | let &mut x = foo; | - | | | first assignment to `x` - | consider changing this to `mut x` + | help: make this binding mutable: `mut x` LL | x += 1; //[ast]~ ERROR cannot assign twice to immutable variable | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/mut/mut-suggestion.nll.stderr b/src/test/ui/mut/mut-suggestion.nll.stderr index 39a1e93d619..9501294a5ab 100644 --- a/src/test/ui/mut/mut-suggestion.nll.stderr +++ b/src/test/ui/mut/mut-suggestion.nll.stderr @@ -1,18 +1,18 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable - --> $DIR/mut-suggestion.rs:21:5 + --> $DIR/mut-suggestion.rs:22:5 | LL | fn func(arg: S) { | --- help: consider changing this to be mutable: `mut arg` -LL | //~^ consider changing this to `mut arg` +... LL | arg.mutate(); | ^^^ cannot borrow as mutable error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable - --> $DIR/mut-suggestion.rs:29:5 + --> $DIR/mut-suggestion.rs:31:5 | LL | let local = S; | ----- help: consider changing this to be mutable: `mut local` -LL | //~^ consider changing this to `mut local` +... LL | local.mutate(); | ^^^^^ cannot borrow as mutable diff --git a/src/test/ui/mut/mut-suggestion.rs b/src/test/ui/mut/mut-suggestion.rs index 0015c8e5c00..af04927c713 100644 --- a/src/test/ui/mut/mut-suggestion.rs +++ b/src/test/ui/mut/mut-suggestion.rs @@ -17,7 +17,8 @@ fn mutate(&mut self) { } fn func(arg: S) { - //~^ consider changing this to `mut arg` + //~^ HELP make this binding mutable + //~| SUGGESTION mut arg arg.mutate(); //~^ ERROR cannot borrow immutable argument //~| cannot borrow mutably @@ -25,7 +26,8 @@ fn func(arg: S) { fn main() { let local = S; - //~^ consider changing this to `mut local` + //~^ HELP make this binding mutable + //~| SUGGESTION mut local local.mutate(); //~^ ERROR cannot borrow immutable local variable //~| cannot borrow mutably diff --git a/src/test/ui/mut/mut-suggestion.stderr b/src/test/ui/mut/mut-suggestion.stderr index 4aa964903f5..b4917887630 100644 --- a/src/test/ui/mut/mut-suggestion.stderr +++ b/src/test/ui/mut/mut-suggestion.stderr @@ -1,18 +1,18 @@ error[E0596]: cannot borrow immutable argument `arg` as mutable - --> $DIR/mut-suggestion.rs:21:5 + --> $DIR/mut-suggestion.rs:22:5 | LL | fn func(arg: S) { - | --- consider changing this to `mut arg` -LL | //~^ consider changing this to `mut arg` + | --- help: make this binding mutable: `mut arg` +... LL | arg.mutate(); | ^^^ cannot borrow mutably error[E0596]: cannot borrow immutable local variable `local` as mutable - --> $DIR/mut-suggestion.rs:29:5 + --> $DIR/mut-suggestion.rs:31:5 | LL | let local = S; - | ----- consider changing this to `mut local` -LL | //~^ consider changing this to `mut local` + | ----- help: make this binding mutable: `mut local` +... LL | local.mutate(); | ^^^^^ cannot borrow mutably diff --git a/src/test/ui/mut/mutable-class-fields.ast.stderr b/src/test/ui/mut/mutable-class-fields.ast.stderr index 0a4d3a0e968..fc12e22815e 100644 --- a/src/test/ui/mut/mutable-class-fields.ast.stderr +++ b/src/test/ui/mut/mutable-class-fields.ast.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to field `nyan.how_hungry` of immutable binding --> $DIR/mutable-class-fields.rs:28:3 | LL | let nyan : cat = cat(52, 99); - | ---- consider changing this to `mut nyan` + | ---- help: make this binding mutable: `mut nyan` LL | nyan.how_hungry = 0; //[ast]~ ERROR cannot assign | ^^^^^^^^^^^^^^^^^^^ cannot mutably borrow field of immutable binding diff --git a/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs new file mode 100644 index 00000000000..e35c8095fa1 --- /dev/null +++ b/src/test/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// run-pass +// +// FIXME(#54366) - We probably shouldn't allow #[thread_local] static mut to get a 'static lifetime. + +#![feature(nll)] +#![feature(thread_local)] + +#[thread_local] +static mut X1: u64 = 0; + +struct S1 { + a: &'static mut u64, +} + +impl S1 { + fn new(_x: u64) -> S1 { + S1 { + a: unsafe { &mut X1 }, + } + } +} + +fn main() { + S1::new(0).a; +} diff --git a/src/test/ui/nll/issue-52669.rs b/src/test/ui/nll/issue-52669.rs new file mode 100644 index 00000000000..17a59997e91 --- /dev/null +++ b/src/test/ui/nll/issue-52669.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +struct A { + b: B, +} + +#[derive(Clone)] +struct B; + +fn foo(_: A) {} + +fn bar(mut a: A) -> B { + a.b = B; + foo(a); + a.b.clone() +} + +fn main() {} diff --git a/src/test/ui/nll/issue-52669.stderr b/src/test/ui/nll/issue-52669.stderr new file mode 100644 index 00000000000..ca1576fad7a --- /dev/null +++ b/src/test/ui/nll/issue-52669.stderr @@ -0,0 +1,13 @@ +error[E0382]: borrow of moved value: `a.b` + --> $DIR/issue-52669.rs:25:5 + | +LL | foo(a); + | - value moved here +LL | a.b.clone() + | ^^^ value borrowed here after move + | + = note: move occurs because `a` has type `A`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-53807.nll.stderr b/src/test/ui/nll/issue-53807.nll.stderr new file mode 100644 index 00000000000..0c019a4ec3c --- /dev/null +++ b/src/test/ui/nll/issue-53807.nll.stderr @@ -0,0 +1,11 @@ +error[E0382]: use of moved value + --> $DIR/issue-53807.rs:14:21 + | +LL | if let Some(thing) = maybe { + | ^^^^^ value moved here in previous iteration of loop + | + = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-53807.rs b/src/test/ui/nll/issue-53807.rs new file mode 100644 index 00000000000..791dee2fb31 --- /dev/null +++ b/src/test/ui/nll/issue-53807.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main(){ + let maybe = Some(vec![true, true]); + loop { + if let Some(thing) = maybe { + } + } +} diff --git a/src/test/ui/nll/issue-53807.stderr b/src/test/ui/nll/issue-53807.stderr new file mode 100644 index 00000000000..7056899d0a4 --- /dev/null +++ b/src/test/ui/nll/issue-53807.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of partially moved value: `maybe` + --> $DIR/issue-53807.rs:14:30 + | +LL | if let Some(thing) = maybe { + | ----- ^^^^^ value used here after move + | | + | value moved here + | + = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` + --> $DIR/issue-53807.rs:14:21 + | +LL | if let Some(thing) = maybe { + | ^^^^^ value moved here in previous iteration of loop + | + = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/move-subpaths-moves-root.rs b/src/test/ui/nll/move-subpaths-moves-root.rs new file mode 100644 index 00000000000..7a4e518f977 --- /dev/null +++ b/src/test/ui/nll/move-subpaths-moves-root.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +fn main() { + let x = (vec![1, 2, 3], ); + drop(x.0); + drop(x); +} diff --git a/src/test/ui/nll/move-subpaths-moves-root.stderr b/src/test/ui/nll/move-subpaths-moves-root.stderr new file mode 100644 index 00000000000..76a1279750f --- /dev/null +++ b/src/test/ui/nll/move-subpaths-moves-root.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-subpaths-moves-root.rs:16:10 + | +LL | drop(x.0); + | --- value moved here +LL | drop(x); + | ^ value used here after move + | + = note: move occurs because `x.0` has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/no-capture-arc.nll.stderr b/src/test/ui/no-capture-arc.nll.stderr index a58d5ad6fa7..31dba18338a 100644 --- a/src/test/ui/no-capture-arc.nll.stderr +++ b/src/test/ui/no-capture-arc.nll.stderr @@ -11,19 +11,6 @@ LL | assert_eq!((*arc_v)[2], 3); | = note: move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait -error[E0382]: borrow of moved value: `arc_v` - --> $DIR/no-capture-arc.rs:26:23 - | -LL | thread::spawn(move|| { - | ------ value moved into closure here -LL | assert_eq!((*arc_v)[3], 4); - | ----- variable moved due to use in closure -... -LL | println!("{:?}", *arc_v); - | ^^^^^ value borrowed here after move - | - = note: move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/no-reuse-move-arc.nll.stderr b/src/test/ui/no-reuse-move-arc.nll.stderr index 902affc8046..bffcae6e2f5 100644 --- a/src/test/ui/no-reuse-move-arc.nll.stderr +++ b/src/test/ui/no-reuse-move-arc.nll.stderr @@ -11,19 +11,6 @@ LL | assert_eq!((*arc_v)[2], 3); //~ ERROR use of moved value: `arc_v` | = note: move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait -error[E0382]: borrow of moved value: `arc_v` - --> $DIR/no-reuse-move-arc.rs:24:23 - | -LL | thread::spawn(move|| { - | ------ value moved into closure here -LL | assert_eq!((*arc_v)[3], 4); - | ----- variable moved due to use in closure -... -LL | println!("{:?}", *arc_v); //~ ERROR use of moved value: `arc_v` - | ^^^^^ value borrowed here after move - | - = note: move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/panic-implementation/panic-implementation-deprecated.stderr b/src/test/ui/panic-implementation/panic-implementation-deprecated.stderr index 43f51447ac4..fabfba94878 100644 --- a/src/test/ui/panic-implementation/panic-implementation-deprecated.stderr +++ b/src/test/ui/panic-implementation/panic-implementation-deprecated.stderr @@ -1,8 +1,8 @@ -error: use of deprecated attribute `panic_implementation`: This attribute was renamed to `panic_handler`. See https://github.com/rust-lang/rust/issues/44489#issuecomment-415140224 +error: use of deprecated attribute `panic_implementation`: this attribute was renamed to `panic_handler`. See https://github.com/rust-lang/rust/issues/44489#issuecomment-415140224 --> $DIR/panic-implementation-deprecated.rs:19:1 | LL | #[panic_implementation] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[panic_handler]` | note: lint level defined here --> $DIR/panic-implementation-deprecated.rs:13:9 diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs new file mode 100644 index 00000000000..2f3c094ff39 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs @@ -0,0 +1,21 @@ +// Adaptation of existing ui test (from way back in +// rust-lang/rust#2329), that starts passing with this feature in +// place. + +// compile-pass + +#![feature(nll)] +#![feature(bind_by_move_pattern_guards)] + +use std::sync::mpsc::channel; + +fn main() { + let (tx, rx) = channel(); + let x = Some(rx); + tx.send(false); + match x { + Some(z) if z.recv().unwrap() => { panic!() }, + Some(z) => { assert!(!z.recv().unwrap()); }, + None => panic!() + } +} diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr new file mode 100644 index 00000000000..4c17ce23b37 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr @@ -0,0 +1,9 @@ +error[E0008]: cannot bind by-move into a pattern guard + --> $DIR/feature-gate.rs:33:16 + | +LL | A { a: v } if *v == 42 => v, + | ^ moves value into pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr new file mode 100644 index 00000000000..4bde9b0c8d9 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr @@ -0,0 +1,10 @@ +error: compilation successful + --> $DIR/feature-gate.rs:42:1 + | +LL | / fn main() { +LL | | foo(107) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr new file mode 100644 index 00000000000..4bde9b0c8d9 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr @@ -0,0 +1,10 @@ +error: compilation successful + --> $DIR/feature-gate.rs:42:1 + | +LL | / fn main() { +LL | | foo(107) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr new file mode 100644 index 00000000000..4bde9b0c8d9 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr @@ -0,0 +1,10 @@ +error: compilation successful + --> $DIR/feature-gate.rs:42:1 + | +LL | / fn main() { +LL | | foo(107) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr new file mode 100644 index 00000000000..4c17ce23b37 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr @@ -0,0 +1,9 @@ +error[E0008]: cannot bind by-move into a pattern guard + --> $DIR/feature-gate.rs:33:16 + | +LL | A { a: v } if *v == 42 => v, + | ^ moves value into pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs new file mode 100644 index 00000000000..f6df4d07baa --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs @@ -0,0 +1,47 @@ +// Check that pattern-guards with move-bound variables is only allowed +// with the appropriate set of feature gates. (Note that we require +// the code to opt into MIR-borrowck in *some* way before the feature +// will work; we use the revision system here to enumerate a number of +// ways that opt-in could occur.) + +// gate-test-bind_by_move_pattern_guards + +// revisions: no_gate gate_and_2015 gate_and_2018 gate_and_znll gate_and_feature_nll + +// (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.) +// ignore-compare-mode-nll + +#![feature(rustc_attrs)] + +#![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))] +#![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))] +#![cfg_attr(gate_and_znll, feature(bind_by_move_pattern_guards))] +#![cfg_attr(gate_and_feature_nll, feature(bind_by_move_pattern_guards))] + +#![cfg_attr(gate_and_feature_nll, feature(nll))] + +//[gate_and_2015] edition:2015 +//[gate_and_2018] edition:2018 +//[gate_and_znll] compile-flags: -Z borrowck=mir + +struct A { a: Box } + +fn foo(n: i32) { + let x = A { a: Box::new(n) }; + let _y = match x { + + A { a: v } if *v == 42 => v, + //[no_gate]~^ ERROR cannot bind by-move into a pattern guard + //[gate_and_2015]~^^ ERROR cannot bind by-move into a pattern guard + + _ => Box::new(0) + }; +} + +#[rustc_error] +fn main() { + foo(107) +} +//[gate_and_2018]~^^^ ERROR compilation successful +//[gate_and_znll]~^^^^ ERROR compilation successful +//[gate_and_feature_nll]~^^^^^ ERROR compilation successful diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs new file mode 100644 index 00000000000..9a9d11ce1b1 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs @@ -0,0 +1,40 @@ +#![feature(nll)] +#![feature(bind_by_move_pattern_guards)] + +// compile-pass + +struct A { a: Box } + +impl A { + fn get(&self) -> i32 { *self.a } +} + +fn foo(n: i32) { + let x = A { a: Box::new(n) }; + let y = match x { + A { a: v } if *v == 42 => v, + _ => Box::new(0), + }; +} + +fn bar(n: i32) { + let x = A { a: Box::new(n) }; + let y = match x { + A { a: v } if x.get() == 42 => v, + _ => Box::new(0), + }; +} + +fn baz(n: i32) { + let x = A { a: Box::new(n) }; + let y = match x { + A { a: v } if *v.clone() == 42 => v, + _ => Box::new(0), + }; +} + +fn main() { + foo(107); + bar(107); + baz(107); +} diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs new file mode 100644 index 00000000000..0fec6b273d3 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs @@ -0,0 +1,16 @@ +#![feature(nll)] +#![feature(bind_by_move_pattern_guards)] + +enum VecWrapper { A(Vec) } + +fn foo(x: VecWrapper) -> usize { + match x { + VecWrapper::A(v) if { drop(v); false } => 1, + //~^ ERROR cannot move out of borrowed content + VecWrapper::A(v) => v.len() + } +} + +fn main() { + foo(VecWrapper::A(vec![107])); +} diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr new file mode 100644 index 00000000000..502006e1b3f --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of borrowed content + --> $DIR/rfc-reject-double-move-across-arms.rs:8:36 + | +LL | VecWrapper::A(v) if { drop(v); false } => 1, + | ^ cannot move out of borrowed content + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs new file mode 100644 index 00000000000..396bfc1c931 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs @@ -0,0 +1,17 @@ +#![feature(nll)] +#![feature(bind_by_move_pattern_guards)] + +struct A { a: Box } + +fn foo(n: i32) { + let x = A { a: Box::new(n) }; + let _y = match x { + A { a: v } if { drop(v); true } => v, + //~^ ERROR cannot move out of borrowed content + _ => Box::new(0), + }; +} + +fn main() { + foo(107); +} diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr new file mode 100644 index 00000000000..dd8f42f7497 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of borrowed content + --> $DIR/rfc-reject-double-move-in-first-arm.rs:9:30 + | +LL | A { a: v } if { drop(v); true } => v, + | ^ cannot move out of borrowed content + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs new file mode 100644 index 00000000000..499a322593c --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 + +// Tests that `meta` is whitelisted, even if the crate doesn't exist +// yet (i.e. it causes a different error than `not-whitelisted.rs`). +use meta; //~ ERROR can't find crate for `meta` + +fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr new file mode 100644 index 00000000000..b8a9b54d26b --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `meta` + --> $DIR/meta.rs:15:5 + | +LL | use meta; //~ ERROR can't find crate for `meta` + | ^^^^ can't find crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs index 826bf675bd6..a259266420a 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs @@ -10,6 +10,6 @@ // edition:2018 -use xcrate::S; //~ ERROR can't find crate for `xcrate` +use xcrate::S; //~ ERROR unresolved import `xcrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr index 27a69ec1b1f..1a8ceec5dac 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0432]: unresolved import `xcrate` --> $DIR/non-existent-1.rs:13:5 | -LL | use xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | use xcrate::S; //~ ERROR unresolved import `xcrate` + | ^^^^^^ Could not find `xcrate` in `{{root}}` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs index 053bf92f4d1..41adb974f21 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs @@ -11,5 +11,6 @@ // edition:2018 fn main() { - let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate` + let s = ::xcrate::S; + //~^ ERROR failed to resolve. Could not find `xcrate` in `{{root}}` } diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr index eb96d5f05d7..b46576b0143 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0433]: failed to resolve. Could not find `xcrate` in `{{root}}` --> $DIR/non-existent-2.rs:14:15 | -LL | let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | let s = ::xcrate::S; + | ^^^^^^ Could not find `xcrate` in `{{root}}` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs index 1b9e5a75e83..0cbeb8cf50f 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs @@ -10,6 +10,6 @@ // edition:2018 -use ycrate; //~ ERROR can't find crate for `ycrate` +use ycrate; //~ ERROR unresolved import `ycrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr index 434bde79a83..31486e14bd2 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `ycrate` +error[E0432]: unresolved import `ycrate` --> $DIR/non-existent-3.rs:13:5 | -LL | use ycrate; //~ ERROR can't find crate for `ycrate` - | ^^^^^^ can't find crate +LL | use ycrate; //~ ERROR unresolved import `ycrate` + | ^^^^^^ no `ycrate` external crate error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs new file mode 100644 index 00000000000..f95961d2a9b --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 + +// Tests that arbitrary crates (other than `core`, `std` and `meta`) +// aren't allowed without `--extern`, even if they're in the sysroot. +use alloc; //~ ERROR unresolved import `alloc` +use test; //~ ERROR unresolved import `test` +use proc_macro; //~ ERROR unresolved import `proc_macro` + +fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr new file mode 100644 index 00000000000..0865bd6bea5 --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/not-whitelisted.rs:15:5 + | +LL | use alloc; //~ ERROR unresolved import `alloc` + | ^^^^^ no `alloc` external crate + +error[E0432]: unresolved import `test` + --> $DIR/not-whitelisted.rs:16:5 + | +LL | use test; //~ ERROR unresolved import `test` + | ^^^^ no `test` external crate + +error[E0432]: unresolved import `proc_macro` + --> $DIR/not-whitelisted.rs:17:5 + | +LL | use proc_macro; //~ ERROR unresolved import `proc_macro` + | ^^^^^^^^^^ no `proc_macro` external crate + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs index 69fc4b4f7f8..b5b1485f662 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:xcrate.rs +// compile-flags:--extern xcrate // edition:2018 use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;` diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr index cfb1a0ac39a..b49291b9c0c 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr @@ -1,17 +1,17 @@ error: crate root imports need to be explicitly named: `use crate as name;` - --> $DIR/single-segment.rs:14:5 + --> $DIR/single-segment.rs:15:5 | LL | use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;` | ^^^^^ error: cannot glob-import all possible crates - --> $DIR/single-segment.rs:15:5 + --> $DIR/single-segment.rs:16:5 | LL | use *; //~ ERROR cannot glob-import all possible crates | ^ error[E0423]: expected value, found module `xcrate` - --> $DIR/single-segment.rs:18:13 + --> $DIR/single-segment.rs:19:13 | LL | let s = ::xcrate; //~ ERROR expected value, found module `xcrate` | ^^^^^^^^ not a value diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs index 7eba02ed444..c17e74c547c 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs @@ -10,6 +10,6 @@ #![feature(extern_in_paths)] -use extern::xcrate::S; //~ ERROR can't find crate for `xcrate` +use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr index c25698c395e..55b8b625507 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0432]: unresolved import `extern::xcrate` --> $DIR/non-existent-1.rs:13:13 | -LL | use extern::xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate` + | ^^^^^^ Could not find `xcrate` in `extern` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs index 4d09a05253e..128ecf41a30 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs @@ -11,5 +11,6 @@ #![feature(extern_in_paths)] fn main() { - let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate` + let s = extern::xcrate::S; + //~^ ERROR failed to resolve. Could not find `xcrate` in `extern` } diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr index b7ca8890c19..7fbe50a9202 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0433]: failed to resolve. Could not find `xcrate` in `extern` --> $DIR/non-existent-2.rs:14:21 | -LL | let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | let s = extern::xcrate::S; + | ^^^^^^ Could not find `xcrate` in `extern` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs index 402d294b2e3..350cca70487 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs @@ -10,6 +10,6 @@ #![feature(extern_in_paths)] -use extern::ycrate; //~ ERROR can't find crate for `ycrate` +use extern::ycrate; //~ ERROR unresolved import `extern::ycrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr index fbea89ae93a..0a49d172169 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `ycrate` - --> $DIR/non-existent-3.rs:13:13 +error[E0432]: unresolved import `extern::ycrate` + --> $DIR/non-existent-3.rs:13:5 | -LL | use extern::ycrate; //~ ERROR can't find crate for `ycrate` - | ^^^^^^ can't find crate +LL | use extern::ycrate; //~ ERROR unresolved import `extern::ycrate` + | ^^^^^^^^^^^^^^ no `ycrate` external crate error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs b/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs index 017844a0252..ea448863703 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:xcrate.rs +// compile-flags:--extern xcrate #![feature(extern_in_paths)] diff --git a/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr b/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr index 8b1dd89fe3c..033bedb3b93 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr @@ -1,17 +1,17 @@ error: cannot glob-import all possible crates - --> $DIR/single-segment.rs:17:5 + --> $DIR/single-segment.rs:18:5 | LL | use extern::*; //~ ERROR cannot glob-import all possible crates | ^^^^^^^^^ error[E0432]: unresolved import `extern` - --> $DIR/single-segment.rs:15:5 + --> $DIR/single-segment.rs:16:5 | LL | use extern; //~ ERROR unresolved import `extern` | ^^^^^^ no `extern` in the root error[E0423]: expected value, found module `extern::xcrate` - --> $DIR/single-segment.rs:20:13 + --> $DIR/single-segment.rs:21:13 | LL | let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate` | ^^^^^^^^^^^^^^ not a value diff --git a/src/test/ui/run-pass/extern/extern-prelude-core.stderr b/src/test/ui/run-pass/extern/extern-prelude-core.stderr new file mode 100644 index 00000000000..f7699531857 --- /dev/null +++ b/src/test/ui/run-pass/extern/extern-prelude-core.stderr @@ -0,0 +1,8 @@ +warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable + --> $DIR/extern-prelude-core.rs:12:12 + | +LL | #![feature(extern_prelude, lang_items, start, alloc)] + | ^^^^^^^^^^^^^^ + | + = note: #[warn(stable_features)] on by default + diff --git a/src/test/ui/run-pass/extern/extern-prelude-std.stderr b/src/test/ui/run-pass/extern/extern-prelude-std.stderr new file mode 100644 index 00000000000..8c059b4ebeb --- /dev/null +++ b/src/test/ui/run-pass/extern/extern-prelude-std.stderr @@ -0,0 +1,8 @@ +warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable + --> $DIR/extern-prelude-std.rs:12:12 + | +LL | #![feature(extern_prelude)] + | ^^^^^^^^^^^^^^ + | + = note: #[warn(stable_features)] on by default + diff --git a/src/test/ui/run-pass/issues/issue-52140/main.rs b/src/test/ui/run-pass/issues/issue-52140/main.rs index c17a4796555..3d727e2ad1b 100644 --- a/src/test/ui/run-pass/issues/issue-52140/main.rs +++ b/src/test/ui/run-pass/issues/issue-52140/main.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:some_crate.rs +// compile-flags:--extern some_crate // edition:2018 mod foo { diff --git a/src/test/ui/run-pass/issues/issue-52141/main.rs b/src/test/ui/run-pass/issues/issue-52141/main.rs index d1003bb2908..20705dc38e1 100644 --- a/src/test/ui/run-pass/issues/issue-52141/main.rs +++ b/src/test/ui/run-pass/issues/issue-52141/main.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:some_crate.rs +// compile-flags:--extern some_crate // edition:2018 use some_crate as some_name; diff --git a/src/test/ui/run-pass/issues/issue-52705/main.rs b/src/test/ui/run-pass/issues/issue-52705/main.rs index 3d828ba60d3..00cb5ac103a 100644 --- a/src/test/ui/run-pass/issues/issue-52705/main.rs +++ b/src/test/ui/run-pass/issues/issue-52705/main.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:png2.rs +// compile-flags:--extern png2 // edition:2018 mod png { diff --git a/src/test/ui/run-pass/macros/macro-comma-support.rs b/src/test/ui/run-pass/macros/macro-comma-support.rs index 9186974f0a3..f674123aac7 100644 --- a/src/test/ui/run-pass/macros/macro-comma-support.rs +++ b/src/test/ui/run-pass/macros/macro-comma-support.rs @@ -62,30 +62,30 @@ fn assert_ne() { #[test] fn cfg() { - cfg!(pants); - cfg!(pants,); - cfg!(pants = "pants"); - cfg!(pants = "pants",); - cfg!(all(pants)); - cfg!(all(pants),); - cfg!(all(pants,)); - cfg!(all(pants,),); + let _ = cfg!(pants); + let _ = cfg!(pants,); + let _ = cfg!(pants = "pants"); + let _ = cfg!(pants = "pants",); + let _ = cfg!(all(pants)); + let _ = cfg!(all(pants),); + let _ = cfg!(all(pants,)); + let _ = cfg!(all(pants,),); } #[test] fn column() { - column!(); + let _ = column!(); } // compile_error! is in a companion to this test in compile-fail #[test] fn concat() { - concat!(); - concat!("hello"); - concat!("hello",); - concat!("hello", " world"); - concat!("hello", " world",); + let _ = concat!(); + let _ = concat!("hello"); + let _ = concat!("hello",); + let _ = concat!("hello", " world"); + let _ = concat!("hello", " world",); } #[test] @@ -131,10 +131,10 @@ fn debug_assert_ne() { #[test] fn env() { - env!("PATH"); - env!("PATH",); - env!("PATH", "not found"); - env!("PATH", "not found",); + let _ = env!("PATH"); + let _ = env!("PATH",); + let _ = env!("PATH", "not found"); + let _ = env!("PATH", "not found",); } #[cfg(std)] @@ -158,58 +158,58 @@ fn eprintln() { #[test] fn file() { - file!(); + let _ = file!(); } #[cfg(std)] #[test] fn format() { - format!("hello"); - format!("hello",); - format!("hello {}", "world"); - format!("hello {}", "world",); + let _ = format!("hello"); + let _ = format!("hello",); + let _ = format!("hello {}", "world"); + let _ = format!("hello {}", "world",); } #[test] fn format_args() { - format_args!("hello"); - format_args!("hello",); - format_args!("hello {}", "world"); - format_args!("hello {}", "world",); + let _ = format_args!("hello"); + let _ = format_args!("hello",); + let _ = format_args!("hello {}", "world"); + let _ = format_args!("hello {}", "world",); } #[test] fn include() { - include!("auxiliary/macro-comma-support.rs"); - include!("auxiliary/macro-comma-support.rs",); + let _ = include!("auxiliary/macro-comma-support.rs"); + let _ = include!("auxiliary/macro-comma-support.rs",); } #[test] fn include_bytes() { - include_bytes!("auxiliary/macro-comma-support.rs"); - include_bytes!("auxiliary/macro-comma-support.rs",); + let _ = include_bytes!("auxiliary/macro-comma-support.rs"); + let _ = include_bytes!("auxiliary/macro-comma-support.rs",); } #[test] fn include_str() { - include_str!("auxiliary/macro-comma-support.rs"); - include_str!("auxiliary/macro-comma-support.rs",); + let _ = include_str!("auxiliary/macro-comma-support.rs"); + let _ = include_str!("auxiliary/macro-comma-support.rs",); } #[test] fn line() { - line!(); + let _ = line!(); } #[test] fn module_path() { - module_path!(); + let _ = module_path!(); } #[test] fn option_env() { - option_env!("PATH"); - option_env!("PATH",); + let _ = option_env!("PATH"); + let _ = option_env!("PATH",); } #[test] @@ -309,10 +309,10 @@ fn unreachable() { #[test] fn vec() { let _: Vec<()> = vec![]; - vec![0]; - vec![0,]; - vec![0, 1]; - vec![0, 1,]; + let _ = vec![0]; + let _ = vec![0,]; + let _ = vec![0, 1]; + let _ = vec![0, 1,]; } // give a test body access to a fmt::Formatter, which seems @@ -340,21 +340,21 @@ fn fmt(&self, $f: &mut fmt::Formatter) -> fmt::Result { test_with_formatter! { #[test] fn write(f: &mut fmt::Formatter) { - write!(f, "hello"); - write!(f, "hello",); - write!(f, "hello {}", "world"); - write!(f, "hello {}", "world",); + let _ = write!(f, "hello"); + let _ = write!(f, "hello",); + let _ = write!(f, "hello {}", "world"); + let _ = write!(f, "hello {}", "world",); } } test_with_formatter! { #[test] fn writeln(f: &mut fmt::Formatter) { - writeln!(f); - writeln!(f,); - writeln!(f, "hello"); - writeln!(f, "hello",); - writeln!(f, "hello {}", "world"); - writeln!(f, "hello {}", "world",); + let _ = writeln!(f); + let _ = writeln!(f,); + let _ = writeln!(f, "hello"); + let _ = writeln!(f, "hello",); + let _ = writeln!(f, "hello {}", "world"); + let _ = writeln!(f, "hello {}", "world",); } } diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.stderr b/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.stderr new file mode 100644 index 00000000000..f95237fbbea --- /dev/null +++ b/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.stderr @@ -0,0 +1,8 @@ +warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable + --> $DIR/crate-path-absolute.rs:12:12 + | +LL | #![feature(crate_in_paths)] + | ^^^^^^^^^^^^^^ + | + = note: #[warn(stable_features)] on by default + diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr b/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr new file mode 100644 index 00000000000..91f918dbd2c --- /dev/null +++ b/src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr @@ -0,0 +1,8 @@ +warning: the feature `crate_in_paths` has been stable since 1.30.0 and no longer requires an attribute to enable + --> $DIR/crate-path-visibility-ambiguity.rs:12:12 + | +LL | #![feature(crate_in_paths)] + | ^^^^^^^^^^^^^^ + | + = note: #[warn(stable_features)] on by default + diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs index c5a356d979d..b13602297a4 100644 --- a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:xcrate.rs +// compile-flags:--extern xcrate // edition:2018 use xcrate::Z; diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs index 3d31c2d3a4d..0d84ccc3d32 100644 --- a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:xcrate.rs +// compile-flags:--extern xcrate #![feature(extern_in_paths)] diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs new file mode 100644 index 00000000000..dfd9fbd2774 --- /dev/null +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs @@ -0,0 +1,24 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-pass +// edition:2018 + +// Tests that `core` and `std` are always available. +use core::iter; +use std::io; +// FIXME(eddyb) Add a `meta` crate to the distribution. +// use meta; + +fn main() { + for _ in iter::once(()) { + io::stdout(); + } +} diff --git a/src/test/ui/run-pass/uniform-paths/basic.rs b/src/test/ui/run-pass/uniform-paths/basic.rs index fbdac98d258..7d997fe493a 100644 --- a/src/test/ui/run-pass/uniform-paths/basic.rs +++ b/src/test/ui/run-pass/uniform-paths/basic.rs @@ -37,7 +37,7 @@ fn main() { { // Test that having `std_io` in a module scope and a non-module // scope is allowed, when both resolve to the same definition. - use std::io as std_io; + use ::std::io as std_io; use std_io::stdout; stdout(); } diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed index fc81ab08f62..36a837509c5 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed @@ -10,6 +10,7 @@ // aux-build:edition-lint-paths.rs // run-rustfix +// compile-flags:--extern edition_lint_paths // edition:2018 // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs index 72751f2080c..9daa4145630 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs @@ -10,6 +10,7 @@ // aux-build:edition-lint-paths.rs // run-rustfix +// compile-flags:--extern edition_lint_paths // edition:2018 // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr index 0ecfd4e4a2c..b3afa2bd1d5 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -1,18 +1,18 @@ error: unused extern crate - --> $DIR/extern-crate-idiomatic-in-2018.rs:21:1 + --> $DIR/extern-crate-idiomatic-in-2018.rs:22:1 | LL | extern crate edition_lint_paths; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here - --> $DIR/extern-crate-idiomatic-in-2018.rs:18:9 + --> $DIR/extern-crate-idiomatic-in-2018.rs:19:9 | LL | #![deny(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)] error: `extern crate` is not idiomatic in the new edition - --> $DIR/extern-crate-idiomatic-in-2018.rs:24:1 + --> $DIR/extern-crate-idiomatic-in-2018.rs:25:1 | LL | extern crate edition_lint_paths as bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic.fixed index a874a622202..0be1f2cc72b 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic.fixed +++ b/src/test/ui/rust-2018/extern-crate-idiomatic.fixed @@ -10,6 +10,7 @@ // run-pass // aux-build:edition-lint-paths.rs +// compile-flags:--extern edition_lint_paths // run-rustfix // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic.rs b/src/test/ui/rust-2018/extern-crate-idiomatic.rs index a874a622202..0be1f2cc72b 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic.rs +++ b/src/test/ui/rust-2018/extern-crate-idiomatic.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:edition-lint-paths.rs +// compile-flags:--extern edition_lint_paths // run-rustfix // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/issue-54006.rs b/src/test/ui/rust-2018/issue-54006.rs new file mode 100644 index 00000000000..ee58d240fcb --- /dev/null +++ b/src/test/ui/rust-2018/issue-54006.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 + +#![no_std] +#![crate_type = "lib"] + +use alloc::vec; +//~^ ERROR unresolved import `alloc` + +pub fn foo() { + let mut xs = vec![]; + //~^ ERROR cannot determine resolution for the macro `vec` + xs.push(0); +} diff --git a/src/test/ui/rust-2018/issue-54006.stderr b/src/test/ui/rust-2018/issue-54006.stderr new file mode 100644 index 00000000000..1183dc9794a --- /dev/null +++ b/src/test/ui/rust-2018/issue-54006.stderr @@ -0,0 +1,17 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/issue-54006.rs:16:5 + | +LL | use alloc::vec; + | ^^^^^ Could not find `alloc` in `{{root}}` + +error: cannot determine resolution for the macro `vec` + --> $DIR/issue-54006.rs:20:18 + | +LL | let mut xs = vec![]; + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed index 995be4290b8..cdae815b200 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.fixed +++ b/src/test/ui/rust-2018/remove-extern-crate.fixed @@ -12,6 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs +// compile-flags:--extern remove_extern_crate #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs index 3ab97a74287..4984da802c0 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.rs +++ b/src/test/ui/rust-2018/remove-extern-crate.rs @@ -12,6 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs +// compile-flags:--extern remove_extern_crate #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr index 752a7b180de..064a853625f 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.stderr +++ b/src/test/ui/rust-2018/remove-extern-crate.stderr @@ -1,24 +1,24 @@ warning: unused extern crate - --> $DIR/remove-extern-crate.rs:18:1 + --> $DIR/remove-extern-crate.rs:19:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here - --> $DIR/remove-extern-crate.rs:16:9 + --> $DIR/remove-extern-crate.rs:17:9 | LL | #![warn(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)] warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:19:1 + --> $DIR/remove-extern-crate.rs:20:1 | LL | extern crate core as another_name; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:32:5 + --> $DIR/remove-extern-crate.rs:33:5 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: convert it to a `use` diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs new file mode 100644 index 00000000000..1f19a05d7a7 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 + +// Dummy import to introduce `uniform_paths` canaries. +use std; + +// fn version() -> &'static str {""} + +mod foo { + // Error wasn't reported, despite `version` being commented out above. + use crate::version; //~ ERROR unresolved import `crate::version` + + fn bar() { + version(); + } +} + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr new file mode 100644 index 00000000000..6dcc451c60a --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `crate::version` + --> $DIR/issue-54253.rs:20:9 + | +LL | use crate::version; //~ ERROR unresolved import `crate::version` + | ^^^^^^^^^^^^^^ no `version` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs new file mode 100644 index 00000000000..7ca5c9e9eae --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 + +#![feature(uniform_paths)] + +// Dummy import to introduce `uniform_paths` canaries. +use std; + +// fn version() -> &'static str {""} + +mod foo { + // Error wasn't reported, despite `version` being commented out above. + use crate::version; //~ ERROR unresolved import `crate::version` + + fn bar() { + version(); + } +} + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr new file mode 100644 index 00000000000..0016e21ef4d --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `crate::version` + --> $DIR/issue-54253.rs:22:9 + | +LL | use crate::version; //~ ERROR unresolved import `crate::version` + | ^^^^^^^^^^^^^^ no `version` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 01c0603256c..d91ff696423 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24 | LL | fn deref_mut_field1(x: Own) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | let __isize = &mut x.y; //~ ERROR cannot borrow | ^ cannot borrow mutably @@ -28,7 +28,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5 | LL | fn assign_field1<'a>(x: Own) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.y = 3; //~ ERROR cannot borrow | ^ cannot borrow mutably @@ -54,7 +54,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5 | LL | fn deref_mut_method1(x: Own) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.set(0, 0); //~ ERROR cannot borrow | ^ cannot borrow mutably @@ -70,7 +70,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6 | LL | fn assign_method1<'a>(x: Own) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | *x.y_mut() = 3; //~ ERROR cannot borrow | ^ cannot borrow mutably diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 3a28ef36d05..62be8e0f73e 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25 | LL | fn deref_mut1(x: Own) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | let __isize = &mut *x; //~ ERROR cannot borrow | ^ cannot borrow mutably @@ -18,7 +18,7 @@ error[E0596]: cannot borrow immutable argument `x` as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6 | LL | fn assign1<'a>(x: Own) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | *x = 3; //~ ERROR cannot borrow | ^ cannot borrow mutably diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index 5bc07949a95..67ee911b381 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -11,7 +11,7 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable --> $DIR/borrowck-object-mutability.rs:29:5 | LL | fn owned_receiver(x: Box) { - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` LL | x.borrowed(); LL | x.borrowed_mut(); //~ ERROR cannot borrow | ^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr index 02fbb5f17ee..0ba48545c60 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr @@ -2,7 +2,7 @@ error[E0595]: closure cannot assign to immutable local variable `x` --> $DIR/unboxed-closure-immutable-capture.rs:23:5 | LL | let x = 0; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | || x = 1; //~ ERROR cannot assign | ^^ cannot borrow mutably @@ -11,7 +11,7 @@ error[E0595]: closure cannot assign to immutable local variable `x` --> $DIR/unboxed-closure-immutable-capture.rs:25:5 | LL | let x = 0; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | || set(&mut x); //~ ERROR cannot assign | ^^ cannot borrow mutably @@ -20,7 +20,7 @@ error[E0595]: closure cannot assign to immutable local variable `x` --> $DIR/unboxed-closure-immutable-capture.rs:26:5 | LL | let x = 0; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | || x = 1; //~ ERROR cannot assign | ^^ cannot borrow mutably @@ -29,7 +29,7 @@ error[E0595]: closure cannot assign to immutable local variable `x` --> $DIR/unboxed-closure-immutable-capture.rs:28:5 | LL | let x = 0; - | - consider changing this to `mut x` + | - help: make this binding mutable: `mut x` ... LL | || set(&mut x); //~ ERROR cannot assign | ^^ cannot borrow mutably diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr index bb2ffcd21b0..4303b4c2f21 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -2,7 +2,7 @@ error[E0595]: closure cannot assign to immutable local variable `tick1` --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:26:17 | LL | let tick1 = || { - | ----- consider changing this to `mut tick1` + | ----- help: make this binding mutable: `mut tick1` ... LL | let tick2 = || { //~ ERROR closure cannot assign to immutable local variable `tick1` | ^^ cannot borrow mutably @@ -11,7 +11,7 @@ error[E0596]: cannot borrow immutable local variable `tick2` as mutable --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:30:5 | LL | let tick2 = || { //~ ERROR closure cannot assign to immutable local variable `tick1` - | ----- consider changing this to `mut tick2` + | ----- help: make this binding mutable: `mut tick2` ... LL | tick2(); //~ ERROR cannot borrow | ^^^^^ cannot borrow mutably diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index 22e11b6977c..1930a929da1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `tick` as mutable --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:17:5 | LL | let tick = || counter += 1; - | ---- consider changing this to `mut tick` + | ---- help: make this binding mutable: `mut tick` LL | tick(); //~ ERROR cannot borrow immutable local variable `tick` as mutable | ^^^^ cannot borrow mutably diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index f9fd6c21b70..9515fe50241 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `tick` as mutable --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:17:5 | LL | let tick = move || counter += 1; - | ---- consider changing this to `mut tick` + | ---- help: make this binding mutable: `mut tick` LL | tick(); //~ ERROR cannot borrow immutable local variable `tick` as mutable | ^^^^ cannot borrow mutably diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr index 1164a864b6b..c0a7f3f0709 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr @@ -2,7 +2,7 @@ error[E0595]: closure cannot assign to immutable local variable `n` --> $DIR/unboxed-closures-mutate-upvar.rs:24:27 | LL | let n = 0; - | - consider changing this to `mut n` + | - help: make this binding mutable: `mut n` LL | let mut f = to_fn_mut(|| { //~ ERROR closure cannot assign | ^^ cannot borrow mutably diff --git a/src/test/ui/writing-to-immutable-vec.stderr b/src/test/ui/writing-to-immutable-vec.stderr index 07e17797139..d1e09521dd8 100644 --- a/src/test/ui/writing-to-immutable-vec.stderr +++ b/src/test/ui/writing-to-immutable-vec.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable local variable `v` as mutable --> $DIR/writing-to-immutable-vec.rs:14:5 | LL | let v: Vec = vec![1, 2, 3]; - | - consider changing this to `mut v` + | - help: make this binding mutable: `mut v` LL | v[1] = 4; //~ ERROR cannot borrow immutable local variable `v` as mutable | ^ cannot borrow mutably diff --git a/src/tools/cargo b/src/tools/cargo index a5d82949485..de314a8b2d4 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a5d82949485802abb45f888d5b8b7f23927f031d +Subproject commit de314a8b2d45bce4958fc23939c5e4286e31621c diff --git a/src/tools/clippy b/src/tools/clippy index daa922393c7..125907ad088 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit daa922393c7417dcee930a880c80668cda3e308a +Subproject commit 125907ad08853b92d35e86aecebcf0f784f348d5 diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 6679ec79c1d..a4d839275c3 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -21,6 +21,7 @@ pub enum Mode { CompileFail, ParseFail, RunFail, + /// This now behaves like a `ui` test that has an implict `// run-pass`. RunPass, RunPassValgrind, Pretty, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index db856a1dcf9..8829d880836 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -199,6 +199,10 @@ pub struct TestProps { pub force_host: bool, // Check stdout for error-pattern output as well as stderr pub check_stdout: bool, + // For UI tests, allows compiler to generate arbitrary output to stdout + pub dont_check_compiler_stdout: bool, + // For UI tests, allows compiler to generate arbitrary output to stderr + pub dont_check_compiler_stderr: bool, // Don't force a --crate-type=dylib flag on the command line pub no_prefer_dynamic: bool, // Run --pretty expanded when running pretty printing tests @@ -249,6 +253,8 @@ pub fn new() -> Self { build_aux_docs: false, force_host: false, check_stdout: false, + dont_check_compiler_stdout: false, + dont_check_compiler_stderr: false, no_prefer_dynamic: false, pretty_expanded: false, pretty_mode: "normal".to_string(), @@ -327,6 +333,14 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) { self.check_stdout = config.parse_check_stdout(ln); } + if !self.dont_check_compiler_stdout { + self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln); + } + + if !self.dont_check_compiler_stderr { + self.dont_check_compiler_stderr = config.parse_dont_check_compiler_stderr(ln); + } + if !self.no_prefer_dynamic { self.no_prefer_dynamic = config.parse_no_prefer_dynamic(ln); } @@ -510,6 +524,14 @@ fn parse_check_stdout(&self, line: &str) -> bool { self.parse_name_directive(line, "check-stdout") } + fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool { + self.parse_name_directive(line, "dont-check-compiler-stdout") + } + + fn parse_dont_check_compiler_stderr(&self, line: &str) -> bool { + self.parse_name_directive(line, "dont-check-compiler-stderr") + } + fn parse_no_prefer_dynamic(&self, line: &str) -> bool { self.parse_name_directive(line, "no-prefer-dynamic") } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2d49c83edb9..401dec7b184 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -247,7 +247,6 @@ fn run_revision(&self) { match self.config.mode { CompileFail | ParseFail => self.run_cfail_test(), RunFail => self.run_rfail_test(), - RunPass => self.run_rpass_test(), RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), DebugInfoGdb => self.run_debuginfo_gdb_test(), @@ -257,13 +256,43 @@ fn run_revision(&self) { CodegenUnits => self.run_codegen_units_test(), Incremental => self.run_incremental_test(), RunMake => self.run_rmake_test(), - Ui => self.run_ui_test(), + RunPass | Ui => self.run_ui_test(), MirOpt => self.run_mir_opt_test(), } } + fn should_run_successfully(&self) -> bool { + let run_pass = match self.config.mode { + RunPass => true, + Ui => self.props.run_pass, + _ => unimplemented!(), + }; + return run_pass && !self.props.skip_codegen; + } + + fn should_compile_successfully(&self) -> bool { + match self.config.mode { + ParseFail | CompileFail => self.props.compile_pass, + RunPass => true, + Ui => self.props.compile_pass, + Incremental => { + let revision = self.revision + .expect("incremental tests require a list of revisions"); + if revision.starts_with("rpass") || revision.starts_with("rfail") { + true + } else if revision.starts_with("cfail") { + // FIXME: would be nice if incremental revs could start with "cpass" + self.props.compile_pass + } else { + panic!("revision name must begin with rpass, rfail, or cfail"); + } + } + mode => panic!("unimplemented for mode {:?}", mode), + } + } + fn check_if_test_should_compile(&self, proc_res: &ProcRes) { - if self.props.compile_pass { + if self.should_compile_successfully() { if !proc_res.status.success() { self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res); } @@ -1677,7 +1706,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C rustc.arg("-Zui-testing"); } } - Ui => { + RunPass | Ui => { if !self .props .compile_flags @@ -1706,7 +1735,7 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C rustc.arg(dir_opt); } - RunPass | RunFail | RunPassValgrind | Pretty | DebugInfoGdb | DebugInfoLldb + RunFail | RunPassValgrind | Pretty | DebugInfoGdb | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits => { // do not use JSON output } @@ -2638,8 +2667,12 @@ fn run_ui_test(&self) { let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); let mut errors = 0; - errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); - errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + if !self.props.dont_check_compiler_stdout { + errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); + } + if !self.props.dont_check_compiler_stderr { + errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + } let modes_to_prune = vec![CompareMode::Nll]; self.prune_duplicate_outputs(&modes_to_prune); @@ -2691,7 +2724,7 @@ fn run_ui_test(&self) { let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - if self.props.run_pass { + if self.should_run_successfully() { let proc_res = self.exec_compiled_test(); if !proc_res.status.success() { diff --git a/src/tools/miri b/src/tools/miri index e6f1e15676c..130d803b324 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit e6f1e15676c26fdc7c4713647fe007b26f361a8e +Subproject commit 130d803b3243a92f5c2d9230935cba7fa88e263e diff --git a/src/tools/rls b/src/tools/rls index fa922de1e5e..2b21611d38a 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit fa922de1e5e1f02b576b7a5aa6ded16935693ec5 +Subproject commit 2b21611d38a16a775f55ea102d8f442dfc51cf6d diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f76c2d4e8cc..72c47273e63 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -51,6 +51,7 @@ "ordslice", // Apache-2.0, rls "cloudabi", // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5) "ryu", // Apache-2.0, rls/cargo/... (b/c of serde) + "bytesize", // Apache-2.0, cargo ]; /// Which crates to check against the whitelist?